| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014 |
- ' Copyright (c) 2013-2026 Bruce A Henderson
- '
- ' Based on the public domain Monkey "trans" by Mark Sibly
- '
- ' This software is provided 'as-is', without any express or implied
- ' warranty. In no event will the authors be held liable for any damages
- ' arising from the use of this software.
- '
- ' Permission is granted to anyone to use this software for any purpose,
- ' including commercial applications, and to alter it and redistribute it
- ' freely, subject to the following restrictions:
- '
- ' 1. The origin of this software must not be misrepresented; you must not
- ' claim that you wrote the original software. If you use this software
- ' in a product, an acknowledgment in the product documentation would be
- ' appreciated but is not required.
- '
- ' 2. Altered source versions must be plainly marked as such, and must not be
- ' misrepresented as being the original software.
- '
- ' 3. This notice may not be removed or altered from any source
- ' distribution.
- '
- Type TExpr
- Field exprType:TType
- Field static:Int
- Method ToString$()
- Return "<TExpr>"
- End Method
- Method Copy:TExpr()
- InternalErr "TExpr.Copy"
- End Method
- Method Semant:TExpr(options:Int = 0)
- InternalErr "TExpr.Semant"
- End Method
- Method SemantSet:TExpr( op$,rhs:TExpr, options:Int = 0 )
- Err ToString()+" cannot be assigned to."
- End Method
- Method SemantFunc:TExpr( args:TExpr[] , throwError:Int = True, funcCall:Int = False )
- 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()
- Local expr:TExpr = New TConstExpr.Create( exprType,Eval() ).Semant()
- If TStringType(TConstExpr(expr).ty) Then
- _appInstance.mapStringConsts(TConstExpr(expr).value)
- End If
- Return expr
- End Method
- Method Trans$()
- Todo
- End Method
- Method TransStmt$()
- Return Trans()
- End Method
- Method TransVar$()
- InternalErr "TExpr.TransVar"
- End Method
- 'semant and cast
- Method SemantAndCast:TExpr( ty:TType,castFlags:Int=0 )
- Local expr:TExpr=Semant()
- 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] Then
- If TIdentExpr(args[i]) Then
- TIdentExpr(args[i]).isArg = True
- End If
- args[i]=args[i].Semant()
- ' if an arg is a invocation without braces, it is *probably* a function pointer.
- If TInvokeExpr(args[i]) And Not TInvokeExpr(args[i]).invokedWithBraces Then
- ' but not if we've already processed it...
- If Not (TInvokeExpr(args[i]).decl.attrs & FUNC_PTR) Then
- TInvokeExpr(args[i]).exprType = New TFunctionPtrType
- Local cp:TDecl = TInvokeExpr(args[i]).decl
- cp.Semant
- If TFuncDecl(cp) and TFuncDecl(cp).IsMethod() Then
- Err "Method cannot be used as a function pointer"
- End If
- TInvokeExpr(args[i]).decl = TFuncDecl(TInvokeExpr(args[i]).decl.Copy(False))
- TInvokeExpr(args[i]).decl.actual = cp
- TInvokeExpr(args[i]).decl.attrs :| FUNC_PTR
- TFunctionPtrType(TInvokeExpr(args[i]).exprType).func = TInvokeExpr(args[i]).decl
- TInvokeExpr(args[i]).decl.semant()
- End If
- End If
-
- End If
- Next
- Return args
- End Method
- Method CastArgs:TExpr[]( args:TExpr[],funcDecl:TFuncDecl )
- If args.Length>funcDecl.argDecls.Length Then
- Err "Too many function parameters"
- End If
- ' FIXME
- 'args=args.Resize( funcDecl.argDecls.Length )
- ' FIXME
- For Local i:Int=0 Until funcDecl.argDecls.Length
- ' ensure funcdecl args are semanted before trying to use them.
- If Not funcDecl.argDecls[i].IsSemanted() Then
- funcDecl.argDecls[i].Semant()
- End If
-
- If i < args.length And args[i]
- Local argExpr:TExpr = args[i]
- If TInvokeExpr(argExpr) And Not TInvokeExpr(argExpr).invokedWithBraces Then
- If Not IsPointerType(funcDecl.argDecls[i].ty, TType.T_BYTE) And Not TFunctionPtrType(funcDecl.argDecls[i].ty) Then
- Err "Unable to convert from '" + argExpr.exprType.ToString() + "()' to '" + funcDecl.argDecls[i].ty.ToString() + "'"
- End If
- End If
- If TInvokeMemberExpr(argExpr) And Not TInvokeMemberExpr(argExpr).invokedWithBraces Then
- If Not IsPointerType(funcDecl.argDecls[i].ty, TType.T_BYTE) And Not TFunctionPtrType(funcDecl.argDecls[i].ty) Then
- Err "Unable to convert from '" + argExpr.exprType.ToString() + "()' to '" + funcDecl.argDecls[i].ty.ToString() + "'"
- End If
- End If
- If funcDecl.argDecls[i].ty._flags & TType.T_VAR Then
- If TConstExpr(argExpr) Or TBinaryExpr(argExpr) Or (TIndexExpr(argExpr) And TStringType(TIndexExpr(argExpr).expr.exprType)) Or ..
- TInvokeExpr(argExpr) Or TInvokeMemberExpr(argExpr) Or TNewObjectExpr(argExpr) or TNewArrayExpr(argExpr) Then
- Err "Expression for 'Var' parameter must be a variable or an element of an array or pointer"
- End If
- If TVarExpr(argExpr) Or TMemberVarExpr(argExpr) Then
- Local decl:TDecl
- If TVarExpr(argExpr) Then
- decl = TVarExpr(argExpr).decl
- Else
- decl = TMemberVarExpr(argExpr).decl
- End If
- If decl.IsReadOnly() Then
- If TFieldDecl(decl) Then
- Local scope:TFuncDecl = _env.FuncScope()
- If Not scope Or Not scope.IsCtor() Or (decl.ClassScope() <> scope.ClassScope()) Then
- Err "Expression for 'Var' parameter cannot be a ReadOnly variable"
- End If
- Else
- Err "Expression for 'Var' parameter cannot be a ReadOnly variable"
- End If
- End If
- End If
- ' passing a non volatile local as Var from within a Try block?
- If TVarExpr(argExpr) Then
- Local ldecl:TLocalDecl = TLocalDecl(TVarExpr(argExpr).decl)
- If ldecl And Not ldecl.volatile Then
- Local tryStmtDecl:TTryStmtDecl = _env.FindTry()
- If tryStmtDecl And (Not ldecl.declaredInTry Or tryStmtDecl <> ldecl.declaredInTry) Then
- ldecl.volatile = True
- End If
- End If
- End If
- End If
-
- If (funcDecl.argDecls[i].ty._flags & TType.T_VAR) And Not (funcDecl.argDecls[i].ty.EqualsType(argExpr.exprType)) Then
- If (Not TObjectType(funcDecl.argDecls[i].ty)) Or (TObjectType(funcDecl.argDecls[i].ty) And Not argExpr.exprType.ExtendsType(funcDecl.argDecls[i].ty)) Then
- err "Variable for 'Var' parameter is not of matching type"
- End If
- End If
- ' re-test auto array for compatible consts.
- If TArrayExpr(argExpr) And TArrayType(funcDecl.argDecls[i].ty) And TNumericType(TArrayType(funcDecl.argDecls[i].ty).elemType) Then
- TArrayExpr(argExpr).toType = TArrayType(funcDecl.argDecls[i].ty).elemType
- argExpr.exprType = Null
- argExpr.Semant()
- End If
- args[i]=argExpr.Cast( funcDecl.argDecls[i].ty )
- Else If funcDecl.argDecls[i].init
- If i = args.length Then
- ' extend args to add default init entry
- args = args[..i + 1]
- End If
- 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, balancePtrs:Int = True )
- If TStringType( lhs ) Or TStringType( rhs ) Then
- If TObjectType(lhs) Or TObjectType(rhs) Then
- If TObjectType(lhs) And TObjectType(lhs).classDecl.ident = "Object" Then
- Return lhs
- End If
- If TObjectType(rhs) And TObjectType(rhs).classDecl.ident = "Object" Then
- Return rhs
- End If
- Return New TStringType
- Else
- Return New TStringType
- End If
- End If
- If IsPointerType( lhs, 0, TType.T_POINTER ) Or IsPointerType( rhs, 0, TType.T_POINTER ) Then
- If balancePtrs Then
- If IsPointerType( lhs, 0, TType.T_POINTER ) Return lhs
- If IsPointerType( rhs, 0, TType.T_POINTER ) Return rhs
- Else
- If IsPointerType( lhs, 0, TType.T_POINTER ) Then
- If Not IsPointerType( rhs, 0, TType.T_POINTER ) And Not TNullType(rhs) Then
- Err "Can't balance types "+lhs.ToString()+" and "+rhs.ToString()+"."
- End If
- Return lhs
- End If
- If IsPointerType( rhs, 0, TType.T_POINTER ) Then
- If Not IsPointerType( lhs, 0, TType.T_POINTER ) And Not TNullType(lhs) Then
- Return rhs
- End If
- End If
- End If
- End If
- If TDouble128Type( lhs ) Or TDouble128Type( rhs ) Return New TDouble128Type
- If TFloat128Type( lhs ) Or TFloat128Type( rhs ) Return New TFloat128Type
- If TFloat64Type( lhs ) Or TFloat64Type( rhs ) Return New TFloat64Type
- If TDoubleType( lhs ) Or TDoubleType( rhs ) Return New TDoubleType
- If TFloatType( lhs ) Or TFloatType( rhs ) Return New TFloatType
- If TFunctionPtrType( lhs ) Or TFunctionPtrType( rhs ) Then
- If TFunctionPtrType( lhs ) Return lhs
- If TFunctionPtrType( rhs ) Return rhs
- End If
- If TInt128Type( lhs ) Or TInt128Type( rhs ) Return New TInt128Type
- If TULongType( lhs ) Or TULongType( rhs ) Return New TULongType
- If TSizeTType( lhs ) Or TSizeTType( rhs ) Return New TSizeTType
- If TWParamType( lhs ) Or TWParamType( rhs ) Return New TWParamType
- If TLongType( lhs ) And TUIntType( rhs ) Return New TULongType
- If TUIntType( lhs ) And TLongType( rhs ) Return New TULongType
- If TLParamType( lhs ) Or TLParamType( rhs ) Return New TLParamType
- If TULongIntType( lhs ) Or TULongIntType( rhs ) Return New TULongIntType
- If TLongType( lhs ) Or TLongType( rhs ) Return New TLongType
- If TLongIntType( lhs ) Or TLongIntType( rhs ) Return New TLongIntType
- If TUIntType( lhs ) Or TUIntType( rhs ) Return New TUIntType
- If TIntType( lhs ) Or TIntType( rhs ) Return New TIntType
- If TEnumType( lhs ) Or TEnumType( rhs ) Then
- If TEnumType( lhs ) Return lhs
- If TEnumType( rhs ) Return rhs
- End If
- If TObjectType( lhs ) And TNullDecl(TObjectType( lhs ).classDecl) Then
- Return rhs
- End If
- If TObjectType( rhs ) And TNullDecl(TObjectType( rhs ).classDecl) Then
- Return lhs
- End If
- If lhs.ExtendsType( rhs ) Return rhs
- If rhs.ExtendsType( lhs ) Return lhs
- ' balance arrays - only for objects... to the lowest common denominator.
- If TArrayType( lhs ) And TArrayType( rhs ) Then
- If TArrayType( lhs ).isStatic - TArrayType( rhs ).isStatic <> 0 Then
- Err "Cannot mix arrays and static arrays"
- End If
-
- If TObjectType(TArrayType( lhs ).elemType) And TObjectType(TArrayType( rhs ).elemType) Then
- ' lhs = Object[]
- If TObjectType(TArrayType( lhs ).elemType).classDecl.ident = "Object" Then
- Return lhs
- End If
- ' rhs = Object[]
- If TObjectType(TArrayType( rhs ).elemType).classDecl.ident = "Object" Then
- Return rhs
- End If
-
- ' does one extend the other? If so, return the base type
- If TObjectType(TArrayType( lhs ).elemType).ExtendsType(TObjectType(TArrayType( rhs ).elemType)) Then
- Return rhs
- End If
- If TObjectType(TArrayType( rhs ).elemType).ExtendsType(TObjectType(TArrayType( lhs ).elemType)) Then
- Return lhs
- End If
-
- ' no? then we will fallback to an Object type array
-
- ' find the Object classdecl instance
- Local modid$="brl.classes"
- Local mdecl:TModuleDecl=_env.FindModuleDecl( modid )
- ' return an array of Objects
- Return New TArrayType.Create(New TObjectType.Create(TClassDecl(mdecl.FindDecl( "object" ))))
- End If
-
- If TObjectType(TArrayType( lhs ).elemType) And TObjectType(TArrayType( lhs ).elemType).classDecl.ident = "Object" And TStringType(TArrayType( rhs ).elemType) Then
- Return lhs
- End If
- If TObjectType(TArrayType( rhs ).elemType) And TObjectType(TArrayType( rhs ).elemType).classDecl.ident = "Object" And TStringType(TArrayType( lhs ).elemType) Then
- Return rhs
- End If
- If TObjectType(TArrayType( lhs ).elemType) And TObjectType(TArrayType( lhs ).elemType).classDecl.ident = "Object" And TArrayType(TArrayType( rhs ).elemType) Then
- Return lhs
- End If
- If TObjectType(TArrayType( rhs ).elemType) And TObjectType(TArrayType( rhs ).elemType).classDecl.ident = "Object" And TArrayType(TArrayType( lhs ).elemType) Then
- Return rhs
- End If
- ' balancing primitive types
- If Not TArrayType( lhs ).elemType.EqualsType(TArrayType( rhs ).elemType) Then
- Err "Types '" + TArrayType( lhs ).elemType.ToString() + " Array' and '" + TArrayType( rhs ).elemType.ToString() + " Array' are unrelated"
- End If
-
- End If
- ' balance structs
- If TObjectType( lhs ) And TObjectType( rhs ) And TObjectType( lhs ).EqualsType(rhs) And TObjectType( lhs ).classDecl.IsStruct() And TObjectType( rhs ).classDecl.IsStruct() Then
- Return lhs
- End If
-
- Err "Can't balance types "+lhs.ToString()+" and "+rhs.ToString()+"."
- End Method
- Function CopyExpr:TExpr( expr:TExpr )
- If Not expr Return Null
- Return expr.Copy()
- End Function
- Function CopyArgs:TExpr[]( exprs:TExpr[] )
- exprs=exprs[..]
- For Local i:Int=0 Until exprs.Length
- exprs[i]=CopyExpr( exprs[i] )
- Next
- Return exprs
- End Function
- 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()
- If exprType Return Self
- Return New TStmtExpr.Create( stmt,CopyExpr(expr) )
- End Method
- Method ToString$()
- Return "TStmtExpr(,"+expr.ToString()+")"
- End Method
- Method Semant:TExpr(options:Int = 0)
- If exprType Return Self
- stmt.Semant()
- expr=expr.Semant()
- exprType=expr.exprType
- Return Self
- End Method
- Method Trans$()
- Return _trans.TransStmtExpr( Self )
- End Method
- Method TransVar$()
- Semant
- Return _trans.TransStmtExpr( Self )
- End Method
- End Type
- ' literal
- Type TConstExpr Extends TExpr
- Field ty:TType
- Field value$
- Field originalValue$
- ' True if the const was identified as a specific type.
- Field typeSpecific:Int
- Method Create:TConstExpr( ty:TType,value$ )
- originalValue = value
-
- If TNumericType( ty ) And IsPointerType(ty, 0, TType.T_POINTER) Then
- Self.ty=ty
- If value Then
- Self.value = value
- Else
- Self.value="0"
- End If
- Return Self
- End If
-
- If TIntType( ty ) Or TShortType( ty ) Or TByteType( ty ) Or TLongType( ty ) Or TUIntType( ty ) Or TULongType( ty ) Or TWParamType(ty) Or TLParamType(ty) Or TLongIntType(ty) Or TULongIntType(ty) Or TSizeTType(ty) Then
- Local radix:Int
- If value.StartsWith( "%" )
- radix=1
- Else If value.StartsWith( "$" )
- radix=4
- EndIf
- If radix
- If radix = 4 Then
- value = HexToDecString(value[1..])
- value = WrapForType(value, ty)
- Else
- Local val:Long = 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
- If TIntType(ty) And val >= 2147483648:Long Then
- value = String( -2147483648:Long + (val - 2147483648:Long))
- Else
- If TShortType( ty ) Then
- value=String( Short(val) )
- Else If TByteType( ty ) Then
- value=String( Byte(val) )
- Else
- value=String( val )
- End If
- End If
- End If
- Else
- Local buf:Byte[64]
- Local b:Int
- Local v:String = value.Trim()
- Local leading0:Int = True
- If v Then
- Local i:Int
- If v[0] = Asc("+") Then
- i = 1
- Else If v[0] = Asc("-") Then
- i = 1
- buf[b] = Asc("-")
- b:+ 1
- End If
-
- While i < v.Length
- If Not IsDigit(v[i]) Then
- Exit
- End If
- If leading0 And v[i] = Asc("0") Then
- i :+ 1
- Continue
- End If
- leading0 = False
- buf[b] = v[i]
-
- b :+ 1
- i :+ 1
- Wend
- Local cleaned:String
- If leading0 Then
- cleaned = "0"
- Else
- cleaned = String.FromBytes(buf, b)
- End If
- value = WrapForType(cleaned, ty)
- Else
- value = "0"
- End If
- EndIf
- Else If TDecimalType( ty )
- If Not (value.Contains("e") Or value.Contains("E") Or value.Contains(".") Or value.Contains("inf") Or value.Contains("nan") Or value.Contains("NaN") Or value.Contains("Inf"))
- If TFloatType(ty) Then
- value:+".00000000"
- Else
- value:+".0000000000000000"
- End If
- EndIf
- EndIf
- Self.ty=ty
- Self.value=value
- Return Self
- End Method
- Method WrapForType:String(num:String, ty:TType)
- Local wrapped:String
- If TIntType(ty) Then
- wrapped = WrapDecToBitsString(num, 32, True)
- Else If TShortType(ty) Then
- wrapped = WrapDecToBitsString(num, 16, False)
- Else If TByteType(ty) Then
- wrapped = WrapDecToBitsString(num, 8, False)
- Else If TUIntType(ty) Then
- wrapped = WrapDecToBitsString(num, 32, False)
- Else If TLongType(ty) Then
- wrapped = WrapDecToBitsString(num, 64, True)
- Else If TULongType(ty) Then
- wrapped = WrapDecToBitsString(num, 64, False)
- Else If TWParamType(ty) Then
- If WORD_SIZE = 4 Then
- wrapped = WrapDecToBitsString(num, 32, False)
- Else
- wrapped = WrapDecToBitsString(num, 64, False)
- End If
- Else If TLParamType(ty) Then
- If WORD_SIZE = 4 Then
- wrapped = WrapDecToBitsString(num, 32, True)
- Else
- wrapped = WrapDecToBitsString(num, 64, True)
- End If
- Else If TLongIntType(ty) Then
- If TLongIntType(ty).GetSize() = 4 Then
- wrapped = WrapDecToBitsString(num, 32, True)
- Else
- wrapped = WrapDecToBitsString(num, 64, True)
- End If
- Else If TULongIntType(ty) Then
- If TULongIntType(ty).GetSize() = 4 Then
- wrapped = WrapDecToBitsString(num, 32, False)
- Else
- wrapped = WrapDecToBitsString(num, 64, False)
- End If
- Else If TSizeTType(ty) Then
- If WORD_SIZE = 4 Then
- wrapped = WrapDecToBitsString(num, 32, False)
- Else
- wrapped = WrapDecToBitsString(num, 64, False)
- End If
- End If
- Return wrapped
- End Method
- Method UpdateType(ty:TType)
- typeSpecific = True
- Create(ty, originalValue)
- End Method
- Method Copy:TExpr()
- Local e:TConstExpr = New TConstExpr.Create( ty,value )
- e.originalValue = originalValue
- e.typeSpecific = typeSpecific
- Return e
- End Method
- Method ToString$()
- Return "TConstExpr(~q"+value+"~q)"
- End Method
- Method Semant:TExpr(options:Int = 0)
- 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
- Method SemantAndCast:TExpr( ty:TType,castFlags:Int=0 )
- Local expr:TExpr=Semant()
- If expr.exprType.EqualsType( ty ) Return expr
- If value = "bbNullObject" Then
- Err "bbNullObject"
- Return expr
- End If
- Return New TCastExpr.Create( ty,expr,castFlags ).Semant()
- End Method
-
- Method CompatibleWithType:Int(ty:TType)
- If Not TDecimalType(ty) Then
- If value.Contains("e") Or value.Contains("E") Or value.Contains(".") Or value.Contains("inf") Or value.Contains("nan") Then
- Return False
- End If
-
- Local val:Long = value.ToLong()
-
- If val < 0 Then
- If TByteType(ty) Or TShortType(ty) Or TUIntType(ty) Or TULongType(ty) Or TSizeTType(ty) Or TInt128Type(ty) Or TWParamType(ty) or TULongIntType(ty) Then
- Return False
- End If
- Else
- If TByteType(ty) Then
- If value <> String.FromInt(Byte(Val)) Then
- Return False
- End If
- End If
- If TUIntType(ty) Or ((TSizeTType(ty) Or TWParamType(ty)) And WORD_SIZE = 4) Or (TULongIntType(ty) And TULongIntType(ty).GetSize() = 4) Then
- If val > 4294967296:Long Then
- Return False
- End If
- End If
-
- If TULongType(ty) Or ((TSizeTType(ty) Or TWParamType(ty)) And WORD_SIZE = 8) Or (TULongIntType(ty) And TULongIntType(ty).GetSize() = 8) Then
- If value.length > 20 Then
- Return False
- Else If value.length = 20 Then
- For Local i:Int = 0 Until value.length
- Local v:Int = value[i]
- Local n:Int = "18446744073709551616"[i]
- If v < n Then
- Exit
- Else If v > n Then
- Return False
- End If
- Next
- End If
- End If
- End If
-
- If TShortType(ty) Then
- If value <> String.FromInt(Short(val)) Then
- Return False
- End If
- End If
- If TIntType(ty) Or (TLParamType(ty) And WORD_SIZE = 4) Or (TLongIntType(ty) And TLongIntType(ty).GetSize() = 4) Then
- If value <> String.FromInt(Int(val)) Then
- Return False
- End If
- End If
- If TLongType(ty) Or (TLParamType(ty) And WORD_SIZE = 8) Or (TLongIntType(ty) And TLongIntType(ty).GetSize() = 8) Then
- If value <> String.FromLong(Long(val)) Then
- Return False
- End If
- End If
-
- End If
-
- Return True
- End Method
- Function HexToDecString:String(hex:String)
- ?bmxng
- Local StaticArray digits:Int[32]
- ?Not bmxng
- Local digits:Int[32] ' 2^64 fits in 20 decimal digits; 32 is safe
- ?
- Local nd:Int = 1
- digits[0] = 0
- For Local i:Int = 0 Until hex.Length
- Local ch:Int = hex[i]
- Local v:Int
- If ch >= 48 And ch <= 57 Then
- v = ch - 48
- Else If ch >= 65 And ch <= 70 Then
- v = ch - 55
- Else If ch >= 97 And ch <= 102 Then
- v = ch - 87
- Else
- ' invalid
- Return ""
- EndIf
- ' multiply current decimal by 16, add v
- Local carry:Int = v
- For Local j:Int = 0 Until nd
- Local x:Int = digits[j] * 16 + carry
- digits[j] = x Mod 10
- carry = x / 10
- Next
- While carry > 0
- If nd >= digits.Length Then
- Err "Overflow: Too many digits"
- Return "0"
- End If
- digits[nd] = carry Mod 10
- carry = carry / 10
- nd :+ 1
- Wend
- Next
- ' strip leading zeros
- While nd > 1 And digits[nd-1] = 0
- nd :- 1
- Wend
- ' build string reversed
- Local sb:TStringBuffer = New TStringBuffer(nd)
- For Local k:Int = nd-1 To 0 Step -1
- sb.AppendChar(digits[k] + 48)
- Next
- Return sb.ToString()
- End Function
- Function WrapDecToBitsString:String( s:String, bits:Int, isSigned:Int )
- If bits<>8 And bits<>16 And bits<>32 And bits<>64 Then
- Return "0"
- End If
- If s.Length = 0 Then
- Return "0"
- End If
- ' --- parse sign ---
- Local i:Int = 0
- Local neg:Int = 0
- Local c0:Int = s[0]
- If c0 = 45 Then ' '-'
- neg = 1
- i = 1
- Else If c0 = 43 Then ' '+'
- i = 1
- End If
- ' --- accumulate modulo 2^64 in (hi, lo) base 2^32 ---
- Local hi:Long = 0
- Local lo:Long = 0
- Const BASE:Long = 4294967296:Long ' 2^32
- Const MASK32:Long = $FFFFFFFF:Long
- For Local k:Int = i Until s.Length
- Local ch:Int = s[k]
- If ch < 48 Or ch > 57 Then
- Exit
- End If
- Local d:Long = (ch - 48)
- ' (hi,lo) = (hi,lo) * 10 + d (mod 2^64)
- Local lo10:Long = lo * 10:Long + d
- Local carry:Long = lo10 / BASE
- lo = lo10 & MASK32
- hi = (hi * 10:Long + carry) & MASK32
- Next
- ' --- apply negative sign as modulo wrap: u = (-u) mod 2^64 ---
- If neg Then
- ' two’s complement negate in 64 bits
- lo = ((~lo) + 1:Long) & MASK32
- If lo = 0 Then
- hi = ((~hi) + 1:Long) & MASK32
- Else
- hi = (~hi) & MASK32
- End If
- End If
- ' --- mask down to requested bit-width (mod 2^bits) ---
- If bits < 64 Then
- If bits <= 32 Then
- Local maskLo:Long
- If bits = 32 Then
- maskLo = MASK32
- Else
- maskLo = (1:Long Shl bits) - 1:Long
- End If
- lo = lo & maskLo
- hi = 0
- Else
- ' bits is 33..63
- Local hiBits:Int = bits - 32
- Local maskHi:Long = (1:Long Shl hiBits) - 1:Long
- hi = hi & maskHi
- lo = lo & MASK32
- End If
- Else
- hi = hi & MASK32
- lo = lo & MASK32
- End If
- ' --- format result ---
- If isSigned Then
- ' signed interpretation
- If bits < 64 Then
- ' sign bit test and subtract 2^bits if set
- If bits <= 32 Then
- Local top:Long = 1:Long Shl (bits - 1)
- Local v:Long = lo
- If (v & top) <> 0 Then v :- (1:Long Shl bits)
- Return String(v)
- Else
- ' 33..63: sign is in hi
- Local signMask:Long = 1:Long Shl ((bits - 32) - 1)
- Local vhi:Long = hi
- Local vlo:Long = lo
- If (vhi & signMask) <> 0 Then
- ' subtract 2^bits: subtract from hi part
- vhi :- (1:Long Shl (bits - 32))
- End If
- ' combine as signed 64 in Long (safe for bits<=63)
- Local v:Long = (vhi Shl 32) | (vlo & MASK32)
- Return String(v)
- End If
- Else
- ' 64-bit signed: just reinterpret (hi,lo) as signed Long
- Local v:Long = (hi Shl 32) | (lo & MASK32)
- Return String(v)
- End If
- Else
- ' unsigned interpretation
- If bits <= 32 Then
- ' lo is 0..2^32-1 and fits in signed Long as positive
- Return String(lo)
- Else
- Return U64ToDecString(hi, lo)
- End If
- End If
- End Function
- ' Convert unsigned 64-bit (hi,lo) base 2^32 to decimal string without ULong.
- Function U64ToDecString:String( hi:Long, lo:Long )
- Const MASK32:Long = $FFFFFFFF:Long
- hi :& MASK32
- lo :& MASK32
- If hi = 0 And lo = 0 Then
- Return "0"
- End If
- If hi = 0 Then
- Return String(lo)
- End If
- Const BASE:Long = 4294967296:Long ' 2^32
- ' collect digits in reverse (max 20 digits for 64-bit)
- ?bmxng
- Local StaticArray buf:Int[32]
- ?not bmxng
- Local buf:Int[32]
- ?
- Local n:Int = 0
- While (hi <> 0) Or (lo <> 0)
- If n >= buf.Length Then
- Err "Overflow: Too many digits"
- Return "0"
- End If
- ' Divide (hi,lo) by 10:
- ' q_hi = hi / 10, r_hi = hi % 10
- ' x = r_hi*2^32 + lo
- ' q_lo = x / 10, r = x % 10
- Local qhi:Long = hi / 10:Long
- Local rhi:Long = hi - qhi * 10:Long
- Local x:Long = rhi * BASE + lo ' fits in signed Long (<= 9*2^32 + (2^32-1))
- Local qlo:Long = x / 10:Long
- Local r:Int = Int(x - qlo * 10:Long)
- hi = qhi & MASK32
- lo = qlo & MASK32
- buf[n] = r + 48
- n :+ 1
- Wend
- Local sb:TStringBuffer = New TStringBuffer(n)
- For Local i:Int = n-1 To 0 Step -1
- sb.AppendChar(buf[i])
- Next
- Return sb.ToString()
- End Function
- 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(options:Int = 0)
- If exprType Return Self
- If Not decl.IsSemanted() InternalErr "TVarExpr.Semant"
- exprType=decl.ty.Copy()
- Return Self
- End Method
- Method SemantSet:TExpr( op$,rhs:TExpr, options:Int = 0 )
- 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(options:Int = 0)
- If exprType Return Self
- If Not decl.IsSemanted() InternalErr "TMemberVarExpr.Semant"
- exprType=decl.ty.Semant()
- Return Self
- End Method
- Method SemantSet:TExpr( op$,rhs:TExpr, options:Int = 0 )
- 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[]
- Field invokedWithBraces:Int
- Field isArg:Int
- Field isRhs:Int
- Method Create:TInvokeExpr( decl:TFuncDecl,args:TExpr[]=Null,invokedWithBraces:Int=True, isArg:Int=False, isRhs:Int = False )
- Self.decl=decl
- If args Then
- Self.args=args
- Else
- Self.args = New TExpr[0]
- End If
- Self.invokedWithBraces = invokedWithBraces
- Self.isArg = isArg
- Self.isRhs = isRhs
- 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(options:Int = 0)
- 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
- 'If ((isArg Or isRhs) And Not invokedWithBraces) And (args = Null Or args.length = 0) Then
- ' if the call was a statement (even one written without parentheses), then invokedWithBraces is true
- ' so no complicated checks are needed here; if invokedWithBraces is false, this is definitely not a call
- If Not invokedWithBraces Then
- If decl.IsMethod() Then
- Err "Method cannot be used as a function pointer"
- End If
- ' nothing to do here, as we are a function pointer. i.e. no braces
- ' and our expression type is a function ptr...
- exprType = New TFunctionPtrType.Create(decl)
-
- Else
- args=CastArgs( args,decl )
- End If
- 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$()
- Return Super.Eval()
- End Method
- End Type
- Type TInvokeMemberExpr Extends TExpr
- Field expr:TExpr
- Field decl:TFuncDecl
- Field args:TExpr[]
- Field isResize:Int 'FIXME - butt ugly!
- Field invokedWithBraces:Int
- Method Create:TInvokeMemberExpr( expr:TExpr,decl:TFuncDecl,args:TExpr[]=Null, invokedWithBraces:Int = True )
- Self.expr=expr
- Self.decl=decl
- If args
- Self.args=args
- Else
- Self.args = New TExpr[0]
- End If
- Self.invokedWithBraces = invokedWithBraces
- 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(options:Int = 0)
- If exprType Return Self
- If Not decl.IsSemanted() decl.Semant()
- exprType=decl.retType
- args=SemantArgs( args )
- 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
- Field instanceExpr:TExpr
- 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(options:Int = 0)
- If exprType Return Self
- Local it:TIdentType = TIdentType(ty)
- Local iArgs:TExpr[] = SemantArgs(CopyArgs(args))
- Local isNewSelf:Int = (it And it.ident = "self")
-
- ty=ty.Semant(True)
- If Not ty Then
- ' maybe it's an instance of a type ?
- Local decl:TVarDecl = TVarDecl(_env.FindDecl(it.ident))
- If decl And TObjectType(decl.ty) Then
- ' this legacy feature is deprecated. Issue a warning but let it go for now...
- ty = decl.ty
- instanceExpr = New TVarExpr.Create(decl).Semant()
- '
- Warn("Use of New <Object instance> is deprecated, and support will be removed in a future update.")
- Else
- Err "Type '"+it.ident+"' not found"
- End If
- Else If isNewSelf Then
- Warn("Use of New Self is deprecated, and support will be removed in a future update.")
- End If
- args=SemantArgs( args )
- Local objTy:TObjectType=TObjectType( ty )
- Local clsTy:TClassType=TClassType( ty )
- If Not objTy And Not clsTy
- Err "Expression is not a class."
- EndIf
-
- If objTy And Not objTy.classDecl.Semanted() Then
- objTy.classDecl.Semant()
- End If
-
- '
- If clsTy And clsTy.instance Then
- instanceExpr = New TSelfExpr.Semant()
- End If
- If objTy Then
- classDecl=objTy.classDecl
- Else
- classDecl=clsTy.classDecl
- End If
- If Not instanceExpr Then
- If classDecl.IsInterface() Err "Cannot create instance of an interface."
- If classDecl.IsAbstract() Err "Cannot create instance of abstract type " + classDecl.ToString() + ..
- ", which is either declared Abstract or has (or inherits) an abstract Method."
- End If
- '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."
- Local parts:String[]
- If it Then
- parts = it.ident.ToLower().Split(".")
- End If
- If classDecl.IsExtern()
- Err "Cannot create instance of an extern type"
- 'If args Err "No suitable constructor found for class "+classDecl.ToString()+"."
- Else
- ' if the New Type doesn't have extra idents (like a create method), then don't use the args in the search.
- ' otherwise, the args are for the constructor.
- If Not parts Or parts.length = 1 Then
- ctor=classDecl.FindFuncDecl( "new",args,,,,,SCOPE_CLASS_HEIRARCHY )
- If Not ctor Err "No suitable constructor found for class "+classDecl.ToString()+"."
- args=CastArgs( args,ctor )
- Else
- ctor=classDecl.FindFuncDecl( "new",,,,,,SCOPE_CLASS_HEIRARCHY )
- If Not ctor Err "No suitable constructor found for class "+classDecl.ToString()+"."
- End If
- EndIf
- ' New Self doesn't necessarily create an instance of ourself - we might be an instance of
- ' a subclass at the time...
- If Not isNewSelf Then
- classDecl.attrs:|CLASS_INSTANCED
- End If
- If TClassType(ty) Then
- exprType=New TObjectType.Create(TClassType(ty).classDecl)
- Else
- exprType=ty
- End If
-
- If it Then
- 'Local parts:String[] = it.ident.ToLower().Split(".")
- Local i:Int = 0
-
- While i < parts.length And parts[i] <> classDecl.IdentLower() And parts[i] <> "self"
- i :+ 1
- Wend
-
- i :+ 1
- Local expr:TExpr = Self
- Local cdecl:TClassDecl = classDecl
- Local eType:TType = ty
-
- Local errorDetails:String
- While i < parts.length
- Local id:String = parts[i]
- i :+ 1
-
- ' find other member decl (field, etc)
- Local decl:TValDecl = TValDecl(cdecl.GetDecl(id))
- If TVarDecl(decl) Then
- decl.Semant
- Local tmp:TLocalDecl=New TLocalDecl.Create( "", eType, expr,, True )
- Local varExpr:TExpr = New TMemberVarExpr.Create(New TVarExpr.Create( tmp ), TVarDecl(decl)).Semant()
- expr = New TStmtExpr.Create( New TDeclStmt.Create( tmp ), varExpr ).Semant()
- eType = decl.ty
- If TObjectType(eType) Then
- cdecl = TObjectType(expr.exprType).classdecl
- End If
- If TArrayType(eType) Or TStringType(eType) Then
- cdecl = eType.GetClass()
- End If
- Continue
- End If
- If TConstDecl(decl) Then
- decl.Semant()
- expr = New TConstExpr.Create(decl.ty, TConstDecl(decl).value).Semant()
- eType = decl.ty
- Continue
- End If
- ' find member function.method
- Local fdecl:TFuncDecl
- Try
- fdecl = cdecl.FindFuncDecl(id, iArgs,,,,True,SCOPE_CLASS_HEIRARCHY)
- Catch errorMessage:String
- If errorMessage.StartsWith("Compile Error") Then
- Throw errorMessage
- Else
- ' couldn't find an exact match, look elsewhere
- If errorMessage.StartsWith("Unable") Then
- errorDetails = errorMessage
- End If
- End If
- End Try
- If fdecl Then
- expr = New TInvokeMemberExpr.Create( expr,fdecl, iArgs ).Semant()
- eType = expr.exprType
- If TObjectType(eType) Then
- cdecl = TObjectType(expr.exprType).classdecl
- End If
- If TArrayType(eType) Or TStringType(eType) Then
- cdecl = eType.GetClass()
- End If
- Continue
- End If
-
- ' didn't match member or function??
- ' probably an error...
- If errorDetails Then
- Err errorDetails
- Else
- Err "Identifier '" + id + "' not found."
- End If
- Wend
-
- Return expr
- End If
- 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 "TNewArrayExpr.Copy"
- Local cexpr:TExpr[expr.length]
- For Local i:Int = 0 Until expr.length
- cexpr[i] = CopyExpr(expr[i])
- Next
- Return New TNewArrayExpr.Create( ty,cexpr )
- End Method
- Method Semant:TExpr(options:Int = 0)
- If exprType Return Self
- ty=ty.Semant()
- exprType=New TArrayType.Create( ty, expr.length )
- For Local i:Int = 0 Until expr.length
- expr[i]=expr[i].SemantAndCast( New TIntType )
- Next
- 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 origFuncDecl:TFuncDecl
- Field funcDecl:TFuncDecl
- Field classScope:TClassDecl
- Field superClass:TClassDecl
-
- Field _identLower:String
- Method Create:TInvokeSuperExpr( ident$,args:TExpr[] = Null, _identLower:String = Null )
- Self.ident=ident
- If args Then
- Self.args=args
- Else
- Self.args = New TExpr[0]
- End If
- Self._identLower = _identLower
- Return Self
- End Method
- Method IdentLower:String()
- If Not _identLower Then
- _identLower = ident.ToLower()
- End If
- Return _identLower
- End Method
- Method Copy:TExpr()
- Return New TInvokeSuperExpr.Create( ident,CopyArgs(args), _identLower )
- End Method
- Method Semant:TExpr(options:Int = 0)
- 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 )
- Try
- ' get the local version of the method from local class scope
- origFuncDecl=classScope.FindFuncDecl(IdentLower(),args,,,,True,SCOPE_CLASS_LOCAL)
- Catch errorMessage:String
- If errorMessage.StartsWith("Compile Error") Then
- Throw errorMessage
- Else
- ' if there isn't one, we'll just use a Super version of it anyway as a reference.
- origFuncDecl=classScope.FindFuncDecl(IdentLower(),args,,,,,SCOPE_CLASS_HEIRARCHY)
- End If
- End Try
- funcDecl=superClass.FindFuncDecl( IdentLower(),args,,,,,SCOPE_CLASS_HEIRARCHY )
- If Not funcDecl Err "Can't find superclass method '"+ident+"'."
- ' ensure the super function has been semanted
- funcDecl.Semant()
-
- ' cannot directly call abstract methods
- If funcDecl.isAbstract() Then
- Err "Abstract method '" + funcDecl.ident + "' cannot be accessed directly."
- End If
-
- ' for static scope, we need to change class scope to that of the super class
- If _env.FuncScope().IsStatic() Then
- classScope = TClassDecl(funcDecl.scope)
- End If
-
- 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()
- Local expr:TExpr = New TSelfExpr
- expr.static = static
- Return expr
- End Method
- Method Semant:TExpr(options:Int = 0)
- If exprType Return Self
- If _env.FuncScope().IsStatic() Then
- static = True
- End If
-
- Local scope:TClassDecl = _env.ClassScope()
- If Not scope Then
- Err "'Self' can only be used within methods."
- End If
-
- Local funcScope:TFuncDecl = _env.FuncScope()
- If funcScope.IsAnyMethod() Then
- exprType=New TObjectType.Create( scope )
- TObjectType(exprType).instance = True
- Else
- exprType=New TClassType.Create( scope )
- End If
- Return Self
- End Method
- Method Trans$()
- Return _trans.TransSelfExpr( Self )
- End Method
- End Type
- Const CAST_EXPLICIT:Int=1
- Const CAST_TWO:Int=2
- 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 CheckArrayExpr:TType(src:TType, e:TExpr, last:TType)
- If TNullType(e.exprType) Then
- Err "Auto array element has no type"
- End If
- If TObjectType(TArrayType(ty).elemType) And TObjectType(TArrayType(ty).elemType).classDecl.ident = "Object" And (TStringType(e.exprType) Or TObjectType(e.exprType) Or TArrayType(e.exprType)) Then
- ' array takes generic objects, so we don't care if source elements are the same kinds.
- Else
- If last <> Null And Not last.EqualsType(e.exprType) Then
- Err "Auto array elements must have identical types"
- End If
- If Not TArrayType(ty).elemType.EqualsType(e.exprType) Then
- If (TObjectType(TArrayType(ty).elemType) = Null And TStringType(TArrayType(ty).elemType) = Null) Or (TObjectType(e.exprType) = Null And TStringType(e.exprType) = Null) Then
- Err "Unable to convert from "+src.ToString()+" to "+ty.ToString()+"."
- Else If TStringType(e.exprType) = Null And Not TObjectType(e.exprType).ExtendsType(TObjectType(TArrayType(ty).elemType)) Then
- Err "Unable to convert from "+src.ToString()+" to "+ty.ToString()+"."
- End If
- End If
- End If
-
- Return e.exprType
- End Method
-
- Method CheckArrayType:Int(ty:TArrayType, src:TArrayType)
- If src.dims <> ty.dims Then
- Return False
- End If
- If TObjectType(TArrayType(ty).elemType) Then
- If TObjectType(TArrayType(ty).elemType).classDecl.ident = "Object" And (TStringType(TArrayType(src).elemType) Or TObjectType(TArrayType(src).elemType) Or TArrayType(TArrayType(src).elemType)) Then
- ' array takes generic objects, so we don't care if source elements are the same kinds.
- Else
- If TObjectType(TArrayType(src).elemType) And Not (TObjectType(TArrayType(src).elemType)).ExtendsType(TArrayType(ty).elemType) And Not TArrayType(ty).elemType.EqualsType(TArrayType(src).elemType) Then
- Return False
- End If
- End If
- Else If TArrayType(TArrayType(ty).elemType) And TArrayType(TArrayType(src).elemType) Then
- If Not CheckArrayType(TArrayType(TArrayType(ty).elemType), TArrayType(TArrayType(src).elemType)) Then
- Return False
- End If
- Else If Not TArrayType(ty).elemType.EqualsType(TArrayType(src).elemType) Then
- Return False
- End If
-
- Return True
- End Method
- Method Semant:TExpr(options:Int = 0)
- If exprType Return Self
- ty=ty.Semant()
-
- If TInvokeExpr(expr) Then
- TInvokeExpr(expr).isRhs = True
- Else If TIdentExpr(expr) Then
- TIdentExpr(expr).isRhs = True
- End If
-
- 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
-
- If src._flags & TType.T_VARPTR Then
- exprType = ty
- Return Self
- End If
- If TStringType(ty) And TObjectType(src)
- ' only if explicitly cast
- If flags & CAST_EXPLICIT Then
- exprType = ty
- 'Return Self
- End If
- End If
- '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 If IsPointerType(ty, 0, TType.T_POINTER)
- exprType = ty
- If flags = CAST_EXPLICIT Then
- Return Self
- Else
- If Not TObjectType( src ).classDecl.IsExtern() Then
- Return Self
- Else
- Return expr
- End If
- End If
- Else
- InternalErr "TCastExpr.Semant"
- EndIf
- Local fdecl:TFuncDecl=src.GetClass().FindFuncDecl( op,,,,,,SCOPE_ALL )
- expr=New TInvokeMemberExpr.Create( expr,fdecl ).Semant()
- EndIf
-
- If TNullType(src) And Not TVoidType(ty) And Not (TArrayType(ty) And TArrayType(ty).IsStatic) Then
- exprType = ty
- End If
-
- If TBoolType(src) And (TNumericType(ty) Or TStringType(ty)) Then
- exprType = ty
- End If
-
- If TNumericType(src) And (TNumericType(ty) Or TStringType(ty)) Then
- ' intrinsics can only cast between selves
- If (TIntrinsicType(src) And TIntrinsicType(ty)=Null) Or (TIntrinsicType(ty) And TIntrinsicType(src)=Null) Then
- If TFloat64Type(src) Or TFloat64Type(ty) Then
- If (TFloat64Type(src) And (TLongType(ty) Or TULongType(ty) Or (TLongIntType(ty) And TLongIntType(ty).GetSize() = 8) Or (TULongIntType(ty) And TULongIntType(ty).GetSize() = 8))) Or (TFloat64Type(ty) And (TLongType(src) Or TULongType(src) Or (TLongIntType(src) And TLongIntType(src).GetSize() = 8) Or (TULongIntType(src) And TULongIntType(src).GetSize() = 8))) Then
- ' ok
- Else
- Err "Unable to convert from "+src.ToString()+" to "+ty.ToString()+"."
- End If
- Else
- Err "Unable to convert from "+src.ToString()+" to "+ty.ToString()+"."
- End If
- Else If TIntrinsicType(src) And TIntrinsicType(ty) Then
- If (TFloat64Type(src) And TFloat64Type(ty)=Null) Or (TFloat64Type(ty) And TFloat64Type(src)=Null) Then
- Err "Unable to convert from "+src.ToString()+" to "+ty.ToString()+"."
- End If
- End If
- exprType = ty
- End If
-
- If TObjectType(ty) And (TObjectType(src) Or TStringType(src) Or TArrayType(src)) Then
- exprType = ty
- Return Self
- End If
-
- If TFunctionPtrType(src) And IsPointerType(ty, 0, TType.T_POINTER) Then
- exprType = ty
- End If
- Else If TBoolType( ty )
- If TVoidType( src )
- Err "Cannot convert from Void to Int."
- EndIf
- If flags & CAST_EXPLICIT
- exprType=ty
- EndIf
- Else If ty.ExtendsType( src )
- If flags & CAST_EXPLICIT
- 'if both objects or both non-objects...
- If (TObjectType(ty)<>Null)=(TObjectType(src)<>Null) Then
- exprType=ty
-
- If TFunctionPtrType(ty) And TInvokeExpr(expr) And Not TInvokeExpr(expr).invokedWithBraces Then
- Return expr
- End If
-
- Return Self
- End If
-
- If (TStringType(ty) Or TArrayType(ty)) And TObjectType(src) Then
- exprType=ty
- Return Self
- End If
- 'Else ' if not explicitly cast, we can't just auto-cast it ourselves here.
- 'If (TObjectType(ty)<>Null) And (TObjectType(src)<>Null) exprType=ty
- EndIf
- EndIf
- If TArrayType(ty) And TArrayType(src) Then
- If TArrayType(ty).isStatic - TArrayType(src).isStatic <> 0 Then
- Err "Unable to convert from " + src.ToString() + " to " + ty.ToString()
- End If
- If TArrayType(ty).dims = TArrayType(src).dims Then
- If TArrayExpr(expr) Then
- Local last:TType
- For Local e:TExpr = EachIn TArrayExpr(expr).exprs
- last = CheckArrayExpr(src, e, last)
- Next
- Else
- If TObjectType(TArrayType(ty).elemType) Then
- If TObjectType(TArrayType(ty).elemType).classDecl.ident = "Object" And (TStringType(TArrayType(src).elemType) Or TObjectType(TArrayType(src).elemType) Or TArrayType(TArrayType(src).elemType)) Then
- ' array takes generic objects, so we don't care if source elements are the same kinds.
- Else
- If TObjectType(TArrayType(src).elemType) Then
- If Not (TObjectType(TArrayType(src).elemType)).ExtendsType(TArrayType(ty).elemType) And Not TArrayType(ty).elemType.EqualsType(TArrayType(src).elemType) Then
- Err "Unable to convert from "+src.ToString()+" to "+ty.ToString()+"."
- End If
- Else If Not TArrayType(ty).elemType.EqualsType(TArrayType(src).elemType) Then
- Err "Unable to convert from "+src.ToString()+" to "+ty.ToString()+"."
- End If
- End If
- Else If TArrayType(TArrayType(ty).elemType) And TArrayType(TArrayType(src).elemType) Then
- If Not CheckArrayType(TArrayType(TArrayType(ty).elemType), TArrayType(TArrayType(src).elemType)) Then
- Err "Unable to convert from "+src.ToString()+" to "+ty.ToString()+"."
- End If
- Else If Not TArrayType(ty).elemType.EqualsType(TArrayType(src).elemType) Then
- Err "Unable to convert from "+src.ToString()+" to "+ty.ToString()+"."
- End If
- End If
-
- exprType = ty
- Return Self
- End If
- End If
- 'If TStringType(src) And TStringVarPtrType(ty) Then
- ' exprType = ty
- ' Return Self
- 'End If
- ' If TArrayType(src) And TPointerType(ty) Then
- ' exprType = ty
- ' Return expr
- ' End If
- If TFunctionPtrType(ty) And TInvokeExpr(expr) Then
- ' a function ptr to function ptr
- If Not TInvokeExpr(expr).invokedWithBraces Then
- src = New TFunctionPtrType
- TFunctionPtrType(src).func = TInvokeExpr(expr).decl
- ' signatures should match
- If TInvokeExpr(expr).decl.equalsFunc(TFunctionPtrType(ty).func) Then
- exprType = ty
- Return expr
- End If
- Else
- ' return type should be function ptr?
- Local retType:TType = expr.exprType
- If TFunctionPtrType(retType) And TFunctionPtrType(ty).func.EqualsFunc(TFunctionPtrType(retType).func) Then
- exprType = retType
- Return expr
- End If
- End If
- End If
- 'If TIntType(ty) And Not IsPointerType(ty, 0, TType.T_POINTER) And IsPointerType(src, 0, TType.T_POINTER) Then
- ' exprType = ty
- ' If flags & CAST_EXPLICIT Then
- ' Return Self
- ' End If
- ' Return expr
- 'End If
- ' explicit cast to number
- If IsNumericType(ty) And IsPointerType(src, 0, TType.T_POINTER) Then
- If flags = CAST_EXPLICIT Then
- exprType = ty
- Return Self
- Else
- exprType = Null
- End If
- 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 TObjectType(src) And TObjectType(ty) And (ty._flags & TType.T_VAR) Then ' TODO : May be VARPTR instead?
- 'exprType = NewPointerType(TType.T_BYTE)
- exprType = ty
- Return Self
- End If
-
- If TStringType(src) And ((src._flags & TType.T_CHAR_PTR) Or (src._flags & TType.T_SHORT_PTR)) And TStringType(ty) Then
- exprType = ty
- Return Self
- End If
-
- ' cast from "some kind of object" array to Object[]
- If TArrayType(ty) And TArrayType(src)
- If (TObjectType(TArrayType(src).elemType) Or TStringType(TArrayType(src).elemType) Or TArrayType(TArrayType(src).elemType)) And TObjectType(TArrayType(ty).elemType) Then
- If TObjectType(TArrayType(ty).elemType).classDecl.ident = "Object" Then
- exprType = ty
- Return Self
- End If
- Else
- If TArrayType(ty).dims = TArrayType(src).dims Then
- exprType = ty
- End If
- End If
- End If
-
- If TArrayType(ty) And TObjectType(src)
- If TObjectType(src).classDecl.ident = "___Array" Then
- exprType = ty
- Return expr
- Else If TObjectType(src).classDecl.ident = "Object" And flags & CAST_EXPLICIT Then
- exprType = ty
- Return Self
- End If
- End If
- If IsPointerType(ty, 0, TType.T_POINTER | TType.T_CHAR_PTR | TType.T_SHORT_PTR) Then
- If IsNumericType(src) And Not (src._flags & TType.T_VARPTR) Then
-
- ' no decimal casts to pointers
- If TDecimalType(src) Then
- exprType = Null
- Else
- exprType = ty
- Return Self
- End If
- Else If TNumericType(src) And (src._flags & TType.T_VARPTR) Then
- exprType = expr.exprType
- Else If TObjectType(src) And (src._flags & TType.T_VARPTR) Then
- exprType = expr.exprType
- Else If TArrayType(src) Then
-
- ' for functions and index access, use a new local variable
- If Not TVarExpr(expr) And Not TMemberVarExpr(expr) Then
- Local tmp:TLocalDecl=New TLocalDecl.Create( "", expr.exprType, expr,, True )
- tmp.Semant()
- Local v:TVarExpr = New TVarExpr.Create( tmp )
- expr = New TStmtExpr.Create( New TDeclStmt.Create( tmp ), v ).Semant()
- End If
-
- If TNumericType(TArrayType(src).elemType) Then
- exprType = TNumericType(TArrayType(src).elemType).ToPointer()
- Return Self
- Else
- ' map arrays to byte ptr
- exprType = TType.MapToPointerType(New TByteType)
- End If
- Else If TStringType(src) Then
- exprType = ty
- Return Self
- End If
- End If
-
- If TStringType(src) And TStringType(ty) And (ty._flags & TType.T_VAR) Then
- exprType = ty
- Return Self
- End If
- If TVarPtrType(ty) Then
- If Not TVarExpr(expr) And Not TMemberVarExpr(expr) And Not (TStmtExpr(expr) And TIndexExpr(TStmtExpr(expr).expr)) Then
- If Not TIndexExpr(expr) Or (TIndexExpr(expr) And Not TVarExpr(TIndexExpr(expr).expr) And Not TMemberVarExpr(TIndexExpr(expr).expr)) Then
- Err "Subexpression for 'Varptr' must be a variable or an element of an array, pointer or string"
- End If
- End If
- exprType = src.Copy()
- exprType._flags :| TType.T_VARPTR
- ty = exprType
- Return Self
- End If
-
- If TFunctionPtrType(ty) And IsPointerType(src, 0, TType.T_POINTER) Then
- exprType = ty
- Return Self
- End If
- If TObjectType(ty) And TObjectType(src) And TObjectType(src).classdecl.IsInterface() And flags & CAST_EXPLICIT Then
- exprType = ty
- Return Self
- End If
- If TObjectType(ty) And TObjectType(src) And TObjectType(ty).classdecl.IsInterface() And flags & CAST_EXPLICIT Then
- exprType = ty
- Return Self
- End If
- If TStringType(ty) And TEnumType(src) Then
- exprType = ty
- Return Self
- End If
- If TEnumType(src) And TEnumType(ty) And (ty._flags & TType.T_VAR) Then
- Return expr
- End If
- If TIntegralType(ty) And TEnumType(src) And (flags & CAST_EXPLICIT Or flags & CAST_TWO) Then
- exprType = ty
- Return Self
- End If
-
- If TIntegralType(src) And TEnumType(ty) Then
- If flags & CAST_TWO Then
- exprType = src
- Return Self
- Else If flags & CAST_EXPLICIT Then
- ' validate const
- If TConstExpr( expr ) And Not TEnumType(ty).decl.CastsToEnum(TConstExpr( expr )) Then
- Err "The value " + TConstExpr( expr ).value + " is not valid for enum " + TEnumType(ty).decl.ToString()
- End If
- exprType = ty
- Return Self
- End If
- End If
- If Not exprType
- Err "Unable to convert from "+src.ToString()+" to "+ty.ToString()+"."
- EndIf
- If TConstExpr( expr ) Then
- If TDecimalType(TConstExpr( expr ).ty) And TDecimalType(ty) Then
- Return New TConstExpr.Create(ty, TConstExpr( expr ).value).Semant()
- End If
-
- Local ex:TExpr = EvalConst()
- If flags & CAST_EXPLICIT Then
- Return New TCastExpr.Create(exprType, ex, CAST_EXPLICIT).Semant()
- Else
- Return ex
- End If
- End If
-
- Return Self
- End Method
- Method Eval$()
- Local val$=expr.Eval()
- If TBoolType( exprType )
- If TIntegralType(expr.exprType)
- If Long( val ) Return "1"
- Return ""
- Else If TDecimalType( expr.exprType )
- If Double( 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 TUIntType( exprType )
- Return Long( 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 TULongType( exprType )
- Return Long( val )
- Else If TLongIntType( exprType )
- Return Long( val )
- Else If TULongIntType( exprType )
- Return Long( val )
- Else If TSizeTType( exprType )
- Return Long( val )
- Else If TInt128Type( exprType )
- Return Long( val )
- Else If TFloat128Type( exprType )
- Return Float( val )
- Else If TDouble128Type( exprType )
- Return Float( val )
- Else If TFloat64Type( exprType )
- Return Float( val )
- Else If TStringType( exprType )
- If TBoolType( expr.exprType )
- If val Return "1"
- Return "0"
- EndIf
- Return String( val )
- Else If TByteType( exprType )
- Return Byte( val )
- Else If TWParamType( exprType )
- Return Long( val )
- Else If TLParamType( exprType )
- Return Long( val )
- Else If TObjectType( exprType )
- If TStringType( expr.exprType )
- Return val
- End If
- EndIf
- Return Super.Eval()
- End Method
- Method Trans$()
- Return _trans.TransCastExpr( Self )
- End Method
- Method ToString$()
- Local t$="TCastExpr(" + ty.ToString()
- If expr t:+","+expr.ToString()
- Return t+")"
- 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(options:Int = 0)
- If exprType Return Self
- expr = expr.Semant()
- ' operator overload?
- If TObjectType(expr.exprType) And (op = "+" Or op = "-" Or op = "~~") Then
- 'Local args:TExpr[] = [rhs]
- Try
- Local decl:TFuncDecl = TFuncDecl(TObjectType(expr.exprType).classDecl.FindFuncDecl(op, Null,,,,True,SCOPE_CLASS_HEIRARCHY))
- If decl Then
- Return New TInvokeMemberExpr.Create( expr, decl, Null ).Semant()
- End If
- Catch error:String
- If error.StartsWith("Compile Error") Then
- Throw error
- Else
- Err "Operator " + op + " is not defined for type '" + expr.exprType.ToString() + "'"
- End If
- End Try
- End If
- Select op
- Case "+","-"
- expr=expr.Semant()
- If Not TNumericType( expr.exprType ) Or IsPointerType(expr.exprType) Then
- Err expr.ToString()+" must be numeric for use with unary operator '"+op+"'"
- End If
- exprType=expr.exprType
- ' Remove Var-ness, if required. "expr" will still be "Var"
- If exprType._flags & TType.T_VAR Then
- exprType = exprType.Copy()
- exprType._flags :~ TType.T_VAR
- End If
- Case "~~"
- expr=expr.Semant()
- If Not (TIntegralType(expr.exprType) Or (TEnumType(expr.exprType) And TEnumType(expr.exprType).decl.isFlags)) Or IsPointerType(expr.exprType) Then
- Err "Bitwise complement can only be used with integrals"
- End If
- If TByteType(expr.exprType) Or TShortType(expr.exprType) Then
- expr=expr.SemantAndCast( New TIntType )
- exprType=New TIntType
- Else
- exprType = expr.exprType
- End If
- Case "not"
- expr=expr.SemantAndCast( New TBoolType,CAST_EXPLICIT )
- exprType=New TBoolType
- Default
- InternalErr "TUnaryExpr.Semant"
- End Select
- If TConstExpr( expr ) Return EvalConst()
- Return Self
- End Method
- Method Eval$()
- Local val$=expr.Eval()
- Select op
- Case "~~"
- If TIntType(exprType) Return ~Int( val )
- If TLongType(exprType) Return ~Long( val )
- If TLongIntType(exprType) Return bmx_bitwise_not_longint( val, TLongIntType(exprType).GetSize() )
- If TULongIntType(exprType) Return bmx_bitwise_not_ulongint( val, TULongIntType(exprType).GetSize() )
- ?Not bmxng
- If TUIntType(exprType) Return bmx_bitwise_not_uint( val )
- If TSizeTType(exprType) Return bmx_bitwise_not_sizet( val )
- If TULongType(exprType) Return bmx_bitwise_not_ulong( val )
- ?bmxng
- If TUIntType(exprType) Return ~UInt( val )
- If TSizeTType(exprType) Return ~Size_T( val )
- If TULongType(exprType) Return ~ULong( val )
- ?
- Case "+"
- Return val
- Case "-"
- If val.StartsWith( "-" ) Return val[1..]
- Return "-"+val
- Case "not"
- If val Return ""
- Return "1"
- End Select
- InternalErr "TUnaryExpr.Eval"
- 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
- Method ToString$()
- Return "(" + lhs.ToString() + " " + op + " " + rhs.ToString() + ")"
- End Method
- End Type
- ' * / + / & ~ | ^ shl shr sar
- 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(options:Int = 0)
- If exprType Return Self
- lhs=lhs.Semant()
- If TIdentExpr(rhs) Then
- TIdentExpr(rhs).isRhs = True
- End If
- rhs=rhs.Semant()
-
- ' operator overload?
- If TObjectType(lhs.exprType) Then
- If TObjectType(lhs.exprType).classDecl.IsStruct() and IsPointerType( lhs.exprType, 0, TType.T_POINTER ) Then
- '
- Else
- Local args:TExpr[] = [rhs]
- Try
- Local decl:TFuncDecl = TFuncDecl(TObjectType(lhs.exprType).classDecl.FindFuncDecl(op, args,,,,True,SCOPE_CLASS_HEIRARCHY))
- If decl Then
- Return New TInvokeMemberExpr.Create( lhs, decl, args ).Semant()
- End If
- Catch error:String
- If error.StartsWith("Compile Error") Then
- Throw error
- Else
- Err "Operator " + op + " is not defined between types '" + lhs.exprType.ToString() + "' and '" + rhs.exprType.ToString() + "'"
- End If
- End Try
- End if
- End If
- Local bitEnumOp:Int
- Select op
- Case "&","~~","|","shl","shr","sar"
- If TFloat128Type(lhs.exprType) Then
- exprType=New TInt128Type
- Else If TDouble128Type(lhs.exprType) Then
- exprType=New TInt128Type
- Else If TFloat64Type(lhs.exprType) Then
- exprType=New TInt128Type
- Else If TDoubleType(lhs.exprType) Then
- exprType=New TLongType
- Else If TFloatType(lhs.exprType) Then
- exprType=New TIntType
- Else If TUIntType(lhs.exprType) Then
- exprType=New TUIntType
- Else If TLongType(lhs.exprType) Then
- exprType=New TLongType
- Else If TULongType(lhs.exprType) Then
- exprType=New TULongType
- Else If TLongIntType(lhs.exprType) Then
- exprType=New TLongIntType
- Else If TULongIntType(lhs.exprType) Then
- exprType=New TULongIntType
- Else If TSizeTType(lhs.exprType) Then
- exprType=New TSizeTType
- Else If TWParamType(lhs.exprType) Then
- exprType=New TWParamType
- Else If TLParamType(lhs.exprType) Then
- exprType=New TLParamType
- Else If TEnumType(lhs.exprType) And TEnumType(lhs.exprType).decl.isFlags Then
- exprType = lhs.exprType.Copy()
- bitEnumOp = 2
- Else If TEnumType(rhs.exprType) And TEnumType(rhs.exprType).decl.isFlags Then
- exprType = rhs.exprType.Copy()
- bitEnumOp = 2
- Else
- exprType=New TIntType
- End If
- Case "^"
- If TIntegralType(lhs.exprType) And TIntegralType(rhs.exprType) Then
- exprType=New TLongType
- Else
- exprType=New TDoubleType
- End If
- Default
- exprType=BalanceTypes( lhs.exprType,rhs.exprType )
- If TStringType( exprType )
- If op<>"+"
- Err "Illegal string operator."
- EndIf
- Else If TVoidType( exprType ) Then
- Err "Illegal operation on a void expression."
- Else If Not TNumericType( exprType ) And Not IsPointerType( exprType, 0, TType.T_POINTER ) And Not TArrayType( exprType ) And Not TBoolType( exprType )
- Err "Operator " + op + " is not defined between types '" + lhs.exprType.ToString() + "' and '" + rhs.exprType.ToString() + "'"
- Else If IsPointerType( exprType, 0, TType.T_POINTER ) And op <> "+" And op <> "-" Then
- Err "Illegal expression type."
- Else If IsPointerType( lhs.exprType, 0, TType.T_POINTER ) And IsPointerType( rhs.exprType, 0, TType.T_POINTER ) And op <> "-" Then
- Err "Illegal expression type."
- EndIf
- End Select
- If (op = "+" Or op = "-") And IsPointerType(exprType, 0, TType.T_POINTER) And TNumericType(lhs.exprType) Then
- ' with pointer addition we don't cast the numeric to a pointer
- Else
- lhs=lhs.Cast( exprType, bitEnumOp )
- End If
-
- If (op = "+" Or op = "-") And IsPointerType(exprType, 0, TType.T_POINTER) And TNumericType(rhs.exprType) Then
- ' with pointer addition we don't cast the numeric to a pointer
- Else
- rhs=rhs.Cast( exprType, bitEnumOp )
- End If
-
- If IsPointerType( lhs.exprType, 0, TType.T_POINTER ) And IsPointerType( rhs.exprType, 0, TType.T_POINTER ) And op = "-" Then
- exprType = New TIntType
- End If
- If TConstExpr( lhs ) And TConstExpr( rhs ) Return EvalConst()
-
- If TConstExpr( rhs ) And (op = "/" Or op = "mod") And TIntegralType(rhs.exprType) And Not Long(rhs.Eval()) Then
- Err "Integer division by zero"
- End If
- Return Self
- End Method
- Method Eval$()
- Local lhs$=Self.lhs.Eval()
- Local rhs$=Self.rhs.Eval()
- If TIntType( exprType ) Or TByteType( exprType ) Or TShortType( exprType )
- Local x:Int=Int(lhs),y:Int=Int(rhs)
- Select op
- Case "^" Return Double(lhs)^Double(rhs)
- Case "*" Return x*y
- Case "/"
- If Not y Then
- Err "Integer division by zero"
- End If
- Return x/y
- Case "mod"
- If Not y Then
- Err "Integer division by zero"
- End If
- Return x Mod y
- Case "shl" Return x Shl y
- Case "shr" Return x Shr y
- Case "sar" Return x Sar 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 TLongType( exprType ) Or TInt128Type(exprType) Or TWParamType(exprType) Or TLParamType(exprType) Or TLongIntType(exprType)
- Local x:Long=Long(lhs),y:Long=Long(rhs)
- Select op
- Case "^" Return Double(lhs)^Double(rhs)
- Case "*" Return x*y
- Case "/"
- If Not y Then
- Err "Integer division by zero"
- End If
- Return x/y
- Case "mod"
- If Not y Then
- Err "Integer division by zero"
- End If
- Return x Mod y
- Case "shl" Return x Shl y
- Case "shr" Return x Shr y
- Case "sar" Return x Sar 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 TSizeTType(exprType)
- ?bmxng
- Local x:Size_T=Size_T(lhs),y:Size_T=Size_T(rhs)
- Select op
- Case "^" Return Double(lhs)^Double(rhs)
- Case "*" Return x*y
- Case "/"
- If Not y Then
- Err "Integer division by zero"
- End If
- Return x/y
- Case "mod"
- If Not y Then
- Err "Integer division by zero"
- End If
- Return x Mod y
- Case "shl" Return x Shl y
- Case "shr" Return x Shr y
- Case "sar" Return x Sar y
- Case "+" Return x + y
- Case "-" Return x - y
- Case "&" Return x & y
- Case "~~" Return x ~ y
- Case "|" Return x | y
- End Select
- ?Not bmxng
- Local opInt:Int = OpToInt(op)
- Select op
- Case "^" Return Double(lhs)^Double(rhs)
- Case "/"
- If Not Long(rhs) Then
- Err "Integer division by zero"
- End If
- Return bmx_binarymathexpr_sizet(opInt, lhs, rhs)
- Case "mod"
- If Not Long(rhs) Then
- Err "Integer division by zero"
- End If
- Return bmx_binarymathexpr_sizet(opInt, lhs, rhs)
- Default
- Return bmx_binarymathexpr_sizet(opInt, lhs, rhs)
- End Select
- ?
- Else If TUIntType(exprType)
- ?bmxng
- Local x:UInt=UInt(lhs),y:UInt=UInt(rhs)
- Select op
- Case "^" Return Double(lhs)^Double(rhs)
- Case "*" Return x*y
- Case "/"
- If Not y Then
- Err "Integer division by zero"
- End If
- Return x/y
- Case "mod"
- If Not y Then
- Err "Integer division by zero"
- End If
- Return x Mod y
- Case "shl" Return x Shl y
- Case "shr" Return x Shr y
- Case "sar" Return x Sar y
- Case "+" Return x + y
- Case "-" Return x - y
- Case "&" Return x & y
- Case "~~" Return x ~ y
- Case "|" Return x | y
- End Select
- ?Not bmxng
- Local opInt:Int = OpToInt(op)
- Select op
- Case "^" Return Double(lhs)^Double(rhs)
- Case "/"
- If Not Long(rhs) Then
- Err "Integer division by zero"
- End If
- Return bmx_binarymathexpr_uint(opInt, lhs, rhs)
- Case "mod"
- If Not Long(rhs) Then
- Err "Integer division by zero"
- End If
- Return bmx_binarymathexpr_uint(opInt, lhs, rhs)
- Default
- Return bmx_binarymathexpr_uint(opInt, lhs, rhs)
- End Select
- ?
- Else If TULongType(exprType) Or TULongIntType(exprType)
- ?bmxng
- Local x:ULong=ULong(lhs),y:ULong=ULong(rhs)
- Select op
- Case "^" Return Double(lhs)^Double(rhs)
- Case "*" Return x*y
- Case "/"
- If Not y Then
- Err "Integer division by zero"
- End If
- Return x/y
- Case "mod"
- If Not y Then
- Err "Integer division by zero"
- End If
- Return x Mod y
- Case "shl" Return x Shl y
- Case "shr" Return x Shr y
- Case "sar" Return x Sar y
- Case "+" Return x + y
- Case "-" Return x - y
- Case "&" Return x & y
- Case "~~" Return x ~ y
- Case "|" Return x | y
- End Select
- ?Not bmxng
- Local opInt:Int = OpToInt(op)
- Select op
- Case "^" Return Double(lhs)^Double(rhs)
- Case "/"
- If Not Long(rhs) Then
- Err "Integer division by zero"
- End If
- Return bmx_binarymathexpr_ulong(opInt, lhs, rhs)
- Case "mod"
- If Not Long(rhs) Then
- Err "Integer division by zero"
- End If
- Return bmx_binarymathexpr_ulong(opInt, lhs, rhs)
- Default
- Return bmx_binarymathexpr_ulong(opInt, lhs, rhs)
- End Select
- ?
- Else If TFloatType( exprType )
- Local x:Double=Double(lhs),y:Double=Double(rhs)
- Select op
- Case "^" Return Double(x^y)
- Case "*" Return Float(x * y)
- Case "/" Return Float(x / y)
- Case "mod" Return Float(x Mod y)
- Case "+" Return Float(x + y)
- Case "-" Return Float(x - y)
- End Select
- Else If TDoubleType( exprType ) Or TFloat128Type(exprType) Or TDouble128Type(exprType) Or TFloat64Type(exprType)
- Local x:Double=Double(lhs),y:Double=Double(rhs)
- Select op
- Case "^" Return x^y
- Case "*" Return x * y
- Case "/" Return x / y
- Case "mod" Return x Mod y
- Case "+" Return x + y
- Case "-" Return x - y
- End Select
- Else If TStringType( exprType )
- Select op
- Case "+"
- _appInstance.removeStringConst(lhs)
- _appInstance.removeStringConst(rhs)
- Return lhs+rhs
- End Select
- Else If TEnumType( exprType )
- Local x:Long=Long(lhs),y:Long=Long(rhs)
- Select op
- Case "shl" Return x Shl y
- Case "shr" Return x Shr y
- Case "sar" Return x Sar y
- Case "+" Return x + y
- Case "-" Return x - y
- Case "&" Return x & y
- Case "~~" Return x ~ y
- Case "|" Return x | y
- End Select
- EndIf
- InternalErr "TBinaryMathExpr.Eval"
- 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(options:Int = 0)
- If exprType Return Self
- lhs=lhs.Semant()
- rhs=rhs.Semant()
- ' operator overload?
- If TObjectType(lhs.exprType) Then
-
- If TNullExpr(rhs) And TObjectType(lhs.exprType).classDecl.IsStruct() Then
- If op = "=" Then
- ty=New TBoolType
- exprType=New TBoolType
- If Not IsPointerType(lhs.exprType, 0, TType.T_POINTER) Then
- lhs = New TConstExpr.Create(New TIntType, 1).Semant()
- End If
- rhs = New TConstExpr.Create(New TIntType, 0).Semant()
- Return Self
- Else
- op = "<>"
- ty = New TBoolType
- exprType=New TBoolType
- If Not IsPointerType(lhs.exprType, 0, TType.T_POINTER) Then
- lhs = New TConstExpr.Create(New TIntType, 1).Semant()
- End If
- rhs = New TConstExpr.Create(New TIntType, 0).Semant()
- Return Self
- End If
- End If
-
- Local args:TExpr[] = [rhs]
- Try
- Local decl:TFuncDecl = TFuncDecl(TObjectType(lhs.exprType).classDecl.FindFuncDecl(op, args,,,,True,SCOPE_CLASS_HEIRARCHY))
- If decl Then
- Return New TInvokeMemberExpr.Create( lhs, decl, args ).Semant()
- End If
- Catch error:String
- ' Structs must define an operator overload for the given op
- If TObjectType(lhs.exprType).classDecl.IsStruct() Then
- Err "No overloaded operator '" + op + "' found for " + TObjectType(lhs.exprType).classDecl.ToString()
- End If
- ' otherwise, no overload, continue...
- End Try
- Else If (TArrayType(lhs.exprType) And TArrayType(lhs.exprType).isStatic) Or (TArrayType(rhs.exprType) And TArrayType(rhs.exprType).isStatic) Then
- Err "Static arrays cannot be compared"
- End If
- ty=BalanceTypes( lhs.exprType,rhs.exprType, False )
- lhs=lhs.Cast( ty )
- rhs=rhs.Cast( ty )
- exprType=New TBoolType
- 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 TLongType( ty ) Or TSizeTType( ty ) Or TUIntType( ty ) Or TULongType( ty ) Or TInt128Type(ty) Or TWParamType(ty) Or TLParamType(ty) Or TLongIntType(ty) Or TULongIntType(ty)
- Local lhs:Long=Long( Self.lhs.Eval() )
- Local rhs:Long=Long( 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 TDoubleType( ty ) Or TFloat128Type(ty) Or TDouble128Type(ty) Or TFloat64Type(ty)
- Local lhs:Double=Double( Self.lhs.Eval() )
- Local rhs:Double=Double( 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 "TBinaryCompareExpr.Eval"
- 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(options:Int = 0)
- If exprType Return Self
- lhs=lhs.SemantAndCast( New TBoolType,CAST_EXPLICIT )
- rhs=rhs.SemantAndCast( New TBoolType,CAST_EXPLICIT )
- exprType=New TBoolType
- 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 "TBinaryLogicExpr.Eval"
- 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()
- If exprType Return Self
-
- Local ind:TExpr[]
- For Local i:Int = 0 Until index.length
- ind = ind + [CopyExpr(index[i])]
- Next
- Return New TIndexExpr.Create( CopyExpr(expr),ind )
- End Method
- Method _Semant:TExpr(set:Int, rhs:TExpr)
- If exprType Return Self
- expr=expr.Semant()
- ' for functions and index access, use a new local variable
- If Not TVarExpr(expr) And Not TMemberVarExpr(expr) Then
- Local tmp:TLocalDecl=New TLocalDecl.Create( "", TType.MapVarPointerToPointerType(expr.exprType.Copy()), expr,, True )
- tmp.Semant()
- Local v:TVarExpr = New TVarExpr.Create( tmp )
- expr = New TStmtExpr.Create( New TDeclStmt.Create( tmp ), v ).Semant()
- End If
- For Local i:Int = 0 Until index.length
- If Not TObjectType(expr.exprType) And Not (TNumericType(expr.exprType) And IsPointerType( expr.exprType, 0 , TType.T_POINTER | TType.T_VARPTR)) Then
- index[i]=index[i].SemantAndCast( New TUIntType, True )
- Else
- index[i]=index[i].Semant()
- End If
- Next
-
- ' operator overload?
- If TObjectType(expr.exprType) And Not IsPointerType( expr.exprType, 0 , TType.T_POINTER | TType.T_VARPTR) Then
- Local args:TExpr[]
- Local op:String
- If set Then
- args = index + [rhs]
- op = "[]="
- Else
- args = index
- op = "[]"
- End If
- Try
- Local decl:TFuncDecl = TFuncDecl(TObjectType(expr.exprType).classDecl.FindFuncDecl(op, args,,,,True,SCOPE_CLASS_HEIRARCHY))
- If decl Then
- Return New TInvokeMemberExpr.Create( expr, decl, args ).Semant()
- End If
- Catch error:String
- If error.StartsWith("Compile Error") Then
- Throw error
- Else
- Local istr:String
- Local vstr:String
- If index.length = 1 Then
- istr = " with '" + index[0].exprType.ToString() + "' index"
- Else
- For Local i:TExpr = EachIn index
- istr :+ ", '" + i.exprType.ToString() + "'"
- Next
- istr = " with " + istr[1..] + " indices"
- End If
- If set Then vstr = " and '" + rhs.exprType.ToString() + "' value"
- Err "Operator " + op + istr + vstr + " is not defined for type '" + expr.exprType.ToString() + "'"
- End If
- End Try
- End If
-
- If TStringType( expr.exprType )
- exprType=New TIntType
- If index.length > 1 Then
- Err "Illegal subexpression for string index"
- End If
- Else If TArrayType( expr.exprType )
- exprType= TArrayType( expr.exprType ).elemType
- If index.Length <> TArrayType( expr.exprType ).dims Then
- Err "Wrong number of indices for array. Expected " + TArrayType( expr.exprType ).dims + ", got " + index.Length
- End If
- If TArrayType( expr.exprType ).dims > 1 Then
- ' a multi-dimensional array of arrays is slightly more complex
- If TArrayType(exprType) Then
- Local sizeExpr:TExpr = New TArraySizeExpr.Create(expr, Null, index)
- index = [sizeExpr]
- Local tmp:TLocalDecl=New TLocalDecl.Create( "", NewPointerType(TType.T_UINT), sizeExpr,,True )
- TArraySizeExpr(sizeExpr).val = tmp
- Local stmt:TExpr = New TStmtExpr.Create( New TDeclStmt.Create( tmp ), Self ).Semant()
- stmt.exprType = exprType
- Return stmt
- Else
- Local sizeExpr:TExpr = New TArraySizeExpr.Create(expr, Null, index).Semant()
- index = [sizeExpr]
- Local tmp:TLocalDecl=New TLocalDecl.Create( "", NewPointerType(TType.T_UINT), sizeExpr,,True )
- TArraySizeExpr(sizeExpr).val = tmp
- Local stmt:TExpr = New TStmtExpr.Create( New TDeclStmt.Create( tmp ), Self ).Semant()
- stmt.exprType = exprType
- Return stmt
- End If
- End If
- Else If TNumericType(expr.exprType) And IsPointerType( expr.exprType, 0 , TType.T_POINTER | TType.T_VARPTR)' And Not TFunctionPtrType( expr.exprType )
- exprType=TType.MapPointerToPrim(TNumericType(expr.exprType))
- Else If TObjectType(expr.exprType) And TObjectType(expr.exprType).classDecl.IsStruct() And IsPointerType( expr.exprType, 0 , TType.T_POINTER | TType.T_VARPTR)' And Not TFunctionPtrType( expr.exprType )
- If IsPointerType( expr.exprType, 0 , TType.T_POINTER) Then
- exprType = TType.MapFromPointer(expr.exprType)
- Else
- exprType = expr.exprType
- End If
- Else
- Err "Expression of type '" + expr.exprType.ToString() + "' cannot be indexed"
- EndIf
- Return Self
- End Method
-
- Method Semant:TExpr(options:Int = 0)
- Return _Semant(False, Null)
- End Method
- Method SemantSet:TExpr( op$,rhs:TExpr, options:Int = 0 )
- Return _Semant(True, rhs)
- End Method
-
- Method SemantFunc:TExpr( args:TExpr[] , throwError:Int = True, funcCall:Int = False )
- Local ex:TExpr = Semant()
-
- If TArrayType( expr.exprType ) Then
- If TFunctionPtrType(exprType) Then
- exprType = TFunctionPtrType(exprType).func.retType
- Else
- If funcCall Then
- Err "Expression of type '" + exprType.ToString() + "' cannot be invoked."
- End If
- End If
- End If
-
- Return ex
- End Method
- Method Trans$()
- Return _trans.TransIndexExpr( Self )
- End Method
- Method TransVar$()
- Return _trans.TransIndexExpr( Self )
- End Method
- Method ToString$()
- Return "<TIndexExpr<"+ expr.ToString() +"[" + index[0].ToString() + "]>>"
- 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(options:Int = 0)
- If exprType Return Self
- expr=expr.Semant()
- If (TArrayType( expr.exprType ) And TArrayType( expr.exprType ).dims = 1) Or TStringType( expr.exprType )
- If from from=from.SemantAndCast( New TIntType )
- If term term=term.SemantAndCast( New TIntType )
- exprType=expr.exprType
- ' remove var-ness
- If exprType._flags & TType.T_VAR Then
- exprType = exprType.Copy()
- exprType._flags :~ TType.T_VAR
- End If
- Else
- Err "Slices can only be used with strings or one dimensional 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[]
-
- Field toType:TType
- Method Create:TArrayExpr( exprs:TExpr[] )
- Self.exprs=exprs
- Return Self
- End Method
- Method Copy:TExpr()
- Local expr:TArrayExpr = New TArrayExpr.Create( CopyArgs(exprs) )
- expr.toType = toType
- Return expr
- End Method
- Method Semant:TExpr(options:Int = 0)
- If exprType Return Self
- If TIdentExpr(exprs[0]) Then
- TIdentExpr(exprs[0]).isRhs = True
- End If
- exprs[0]=exprs[0].Semant()
- Local ty:TType=exprs[0].exprType
- ' convert from varptr to ptr if required
- ty = TType.MapVarPointerToPointerType(ty.Copy())
-
- If TInvokeExpr(exprs[0]) And Not TInvokeExpr(exprs[0]).invokedWithBraces Then
- ty = New TFunctionPtrType
- Local cp:TDecl = TInvokeExpr(exprs[0]).decl
- TInvokeExpr(exprs[0]).decl = TFuncDecl(TInvokeExpr(exprs[0]).decl.Copy())
- TInvokeExpr(exprs[0]).decl.actual = cp
- TInvokeExpr(exprs[0]).decl.attrs :| FUNC_PTR
- TFunctionPtrType(ty).func = TInvokeExpr(exprs[0]).decl
- For Local i:Int=1 Until exprs.Length
- If TIdentExpr(exprs[1]) Then
- TIdentExpr(exprs[1]).isRhs = True
- End If
- exprs[i]=exprs[i].Semant()
-
- If TInvokeExpr(exprs[i]) And Not TInvokeExpr(exprs[i]).invokedWithBraces
- cp = TInvokeExpr(exprs[i]).decl
-
- TInvokeExpr(exprs[i]).decl = TFuncDecl(TInvokeExpr(exprs[i]).decl.Copy())
- TInvokeExpr(exprs[i]).decl.actual = cp
- TInvokeExpr(exprs[i]).decl.attrs :| FUNC_PTR
-
- ty=BalanceTypes( ty, New TFunctionPtrType )
- Else
- ty=BalanceTypes( ty,exprs[i].exprType )
- End If
- Next
- Else
- For Local i:Int=1 Until exprs.Length
- exprs[i]=exprs[i].Semant()
- ty=BalanceTypes( ty,exprs[i].exprType )
- Next
- End If
- Local comp:Int = True
- Local last:TType
- Local base:TType
- For Local i:Int=0 Until exprs.Length
- Local expr:TExpr = exprs[i]
- ' don't cast null types
- If TNullType(expr.exprType) <> Null Then
- Err "Auto array element has no type"
- End If
- Local ety:TType = expr.exprType
- If TBoolType(ety) Then
- ety = New TIntType
- End If
-
- If TObjectType(ety) And Not base Then
- base = ety
- End If
-
- If last <> Null And Not last.EqualsType(ety) Then
- If TObjectType(ety) Then
- If base.ExtendsType(ety) Then
- base = ety
- Else If Not ety.ExtendsType(base) Then
- Err "Auto array elements must be compatible types : Index " + i
- End If
- Else
- If (Not TConstExpr(expr) And Not IsNumericType(ety)) Or (TConstExpr(expr) And IsNumericType(ety) And Not TConstExpr(expr).CompatibleWithType(ty)) Then
- Err "Auto array elements must have identical types : Index " + i
- End If
- End If
- End If
-
- If toType And TConstExpr(expr) And Not TConstExpr(expr).CompatibleWithType(toType) Then
- comp = False
- End If
-
- last = ety
-
- exprs[i]=expr.Cast( ty )
- Next
- If comp And toType Then
- exprType=New TArrayType.Create( toType )
- Else
- exprType=New TArrayType.Create( ty )
- End If
- Return Self
- End Method
- Method Trans$()
- Return _trans.TransArrayExpr( Self )
- End Method
- End Type
- Type TArraySizeExpr Extends TExpr
- Field expr:TExpr
- Field val:TDecl
- Field index:TExpr[]
- Method Create:TArraySizeExpr( expr:TExpr, val:TDecl, index:TExpr[] )
- Self.expr=expr
- Self.val=val
- Self.index=index
- Return Self
- End Method
- Method Copy:TExpr()
- Local ind:TExpr[]
- For Local i:Int = 0 Until index.length
- ind = ind + [CopyExpr(index[i])]
- Next
- Return New TArraySizeExpr.Create( CopyExpr(expr), val, ind )
- End Method
- Method Semant:TExpr(options:Int = 0)
- If exprType Return Self
- expr=expr.Semant()
-
- For Local i:Int = 0 Until index.length
- index[i]=index[i].SemantAndCast( New TUIntType )
- Next
-
- exprType=NewPointerType(TType.T_UINT)
- Return Self
- End Method
- Method Trans$()
- Return _trans.TransArraySizeExpr( Self )
- End Method
- Method ToString$()
- Return expr.ToString() + ".Size"
- End Method
- End Type
- Type TIdentTypeExpr Extends TExpr
- Field cdecl:TClassDecl
- Method Create:TIdentTypeExpr( ty:TType )
- Self.exprType=ty
- Return Self
- End Method
- Method Copy:TExpr()
- Return New TIdentTypeExpr.Create( exprType )
- End Method
- Method _Semant()
- If cdecl Return
- exprType=exprType.Semant()
- If TArrayType(exprType) And TObjectType(TArrayType(exprType).elemType) Then
- cdecl=TObjectType(TArrayType(exprType).elemType).classDecl
- Else
- cdecl=exprType.GetClass()
- End If
- If Not cdecl InternalErr "TIdentTypeExpr._Semant"
- End Method
- Method Semant:TExpr(options:Int = 0)
- _Semant
- Err "Expression can't be used in this way"
- End Method
- Method SemantFunc:TExpr( args:TExpr[] , throwError:Int = True, funcCall:Int = False )
- _Semant
- If args.Length=1 And args[0] Then
- If TArrayType(exprType) Then
- Return args[0].Cast( exprType,CAST_EXPLICIT )
- Else
- Return args[0].Cast( cdecl.objectType,CAST_EXPLICIT )
- End If
- End If
- Err "Illegal number of arguments for type conversion"
- End Method
- Method SemantScope:TScopeDecl()
- _Semant
- Return cdecl
- End Method
- Method Trans$()
- Return _trans.TransIdentTypeExpr( Self )
- End Method
- Method Cast:TExpr( ty:TType,castFlags:Int=0 )
- Err "Unable to convert from Type to " + ty.ToString()
- End Method
- End Type
- Type TIdentExpr Extends TExpr
- Field ident$
- Field expr:TExpr
- Field scope:TScopeDecl
- Field static:Int
- Field isArg:Int
- Field isRhs:Int
- Field fixedScope:Int
-
- Field _identLower:String
- Field unknownIdentsEvalFalse:Int
- Method IdentLower:String()
- If Not _identLower Then
- _identLower = ident.ToLower()
- End If
- Return _identLower
- End Method
- Method Create:TIdentExpr( ident$,expr:TExpr=Null, _identLower:String = Null, unknownIdentsEvalFalse:Int = False )
- Self.ident=ident
- Self.expr=expr
- Self._identLower = _identLower
- Self.unknownIdentsEvalFalse = unknownIdentsEvalFalse
- Return Self
- End Method
- Method Copy:TExpr()
- Local i:TIdentExpr = New TIdentExpr.Create( ident,CopyExpr(expr), _identLower )
- i.static = static
- i.isArg = isArg
- i.isRhs = isRhs
- i.fixedScope = fixedScope
- Return i
- 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()
- static = expr.static
- scope=expr.exprType.GetClassScope()
- If Not scope Then
- Local e:String = "Member '" + ident + "' Not found in "
- If expr.exprType Then
- e :+ "type '" + expr.exprType.ToString() + "'"
- Else
- e :+ "'" + expr.ToString() + "'"
- End If
- Err e
- Else
- scope.Semant
- End If
- End If
- fixedScope = True
- Else
- scope=_env
- ' determines if access is via static (like Function, or via a Type)
- ' However, for Field->Field access this is not strictly true.
- If _env.FuncScope()=Null
- static = TModuleDecl(_env) = Null
- Else
- static=_env.FuncScope().IsStatic()
- End If
- 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( errorDetails:String = Null )
- If errorDetails Then
- Err errorDetails
- Else
- Err "Identifier '"+ident+"' not found."
- End If
- End Method
- Method IdentNotFound()
- End Method
- Method IsVar()
- InternalErr "TIdentExpr.IsVar"
- End Method
- Method Semant:TExpr(options:Int = 0)
- Return SemantSet( "",Null, options )
- End Method
- Method SemantSet:TExpr( op$,rhs:TExpr, options:Int = 0 )
- _Semant
- Select options
- Case OPTION_WANT_LOOP_LABEL
-
- Local loopLabel:String = "#" + IdentLower()
-
- ' maybe it's a loop label?
- Local stmt:TLoopStmt = TLoopStmt(scope.FindLoop(loopLabel))
-
- If stmt Then
- Return New TLoopLabelExpr.Create(stmt)
- End If
-
- Return Self
-
- Case OPTION_WANT_DATA_LABEL
- Local loopLabel:String = "#" + IdentLower()
- ' maybe it's a data label?
- Local ddecl:TDefDataDecl = TDefDataDecl(_appInstance.FindDataLabel(loopLabel))
-
- If ddecl Then
- Return New TDataLabelExpr.Create(ddecl)
- End If
-
- Return Self
-
- Default
- 'Local scope:TScopeDecl=IdentScope()
- Local vdecl:TValDecl=scope.FindValDecl( IdentLower(), static )
-
- If TLocalDecl( vdecl )
- ' local variable should (at least) be in the same function scope.
- If vdecl.FuncScope() <> scope.FuncScope() Then
- ' or the local can be in localmain..
- If TModuleDecl(scope) And vdecl.FuncScope() And vdecl.FuncScope().ident = "__LocalMain" Then
- ' ok
- Else
- vdecl = Null
- End If
- End If
- End If
-
- If vdecl And fixedScope And static Then
- If TClassDecl(vdecl.scope) And TClassDecl(scope) Then
- If Not TClassDecl(scope).ExtendsClass(TClassDecl(vdecl.scope)) Then
- vdecl = Null
- End If
- Else
- If vdecl.scope <> scope Then
- vdecl = Null
- End If
- End If
- End If
-
- If vdecl
-
- If op And TLocalDecl( vdecl )
-
- Local ldecl:TLocalDecl = TLocalDecl( vdecl )
-
- If Not ldecl.volatile Then
- Local tryStmtDecl:TTryStmtDecl = scope.FindTry()
- If tryStmtDecl And (Not ldecl.declaredInTry Or tryStmtDecl <> ldecl.declaredInTry) Then
- ldecl.volatile = True
- End If
- End If
-
- Else 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
- Local args:TExpr[]
- If rhs args=[rhs]
- Local decl:TDecl = TDecl(scope.FindDecl(IdentLower()))
- ' maybe it's an enum?
- Local edecl:TEnumValueDecl = TEnumValueDecl(decl)
- If edecl Then
- Return New TIdentEnumExpr.Create(edecl)
- End If
- Local fdecl:TFuncDecl
-
- Try
- fdecl=scope.FindFuncDecl( IdentLower(),args, , isArg, True,True,SCOPE_ALL )
- Catch errorMessage:String
- If errorMessage.StartsWith("Compile Error") Then
- Throw errorMessage
- End If
- End Try
-
- If fdecl
- If Not isArg And Not fdecl.maybeFunctionPtr Err "Identifier '"+ident+"' cannot be used in this way."
-
- fdecl.maybeFunctionPtr = False
-
- If Not fdecl.IsStatic()
- If static Err "Method '"+ident+"' cannot be accessed from here."
- 'If expr Return New TInvokeMemberExpr.Create( expr,fdecl,args, False ).Semant()
- EndIf
-
- Return New TInvokeExpr.Create( fdecl,args, False, isArg, isRhs ).Semant()
- End If
-
- ' maybe it's a classdecl?
- Local cdecl:TClassDecl = TClassDecl(decl)
-
- If cdecl Then
- Local e:TIdentTypeExpr = New TIdentTypeExpr.Create(cdecl.objectType)
- e.cdecl = cdecl
- Return e
- End If
-
- If unknownIdentsEvalFalse Then
- Return New TConstExpr.Create( New TIntType, 0 ).Semant()
- End If
-
- End Select
-
- IdentErr
- End Method
- Method SemantFunc:TExpr( args:TExpr[], throwError:Int = True, funcCall:Int = False )
- _Semant
- Local errorDetails:String
- Local nearestScopeError:String
- 'Local scope:TScopeDecl=IdentScope()
- Local initialScope:Int = SCOPE_ALL
- If scope Then
- If TClassDecl(scope) Then
- initialScope = SCOPE_CLASS_HEIRARCHY
- Else If TModuleDecl(scope) Then
- initialScope = SCOPE_MODULE
- End If
- End If
-
- Local fdecl:TFuncDecl
- Try
- fdecl=scope.FindFuncDecl( IdentLower(),args,,,,True,initialScope )
- ' Local decl:Object=scope.FindFuncDecl( IdentLower(),args,,,,True,SCOPE_ALL )
- ' If decl Then
- ' If TFuncDecl(decl) Then
- ' fdecl = TFuncDecl(decl)
- ' Else If TFuncDeclList(decl) Then
- ' If Not TFuncDeclList(decl).IsEmpty() Then
- ' fdecl = TFuncDecl(TFuncDeclList(decl).First())
- ' End If
- ' End If
- ' End If
- Catch errorMessage:String
- If errorMessage.StartsWith("Compile Error") Then
- Throw errorMessage
- Else
- ' couldn't find an exact match, look elsewhere
- errorDetails = errorMessage
- If errorMessage.StartsWith("Unable") Then
- nearestScopeError = errorDetails
- End If
- End If
- End Try
- ' if our scope is static, but the scope of the found function/method is not
- ' then we should ignore it and continue looking higher up the scope stack.
- If static And fdecl And Not fdecl.IsStatic() Then
- Local scope2:TScopeDecl = fdecl.scope
-
- fdecl = Null
-
- ' if fdecl was a method, this would be the Type's scope (ie. file/module)
- If scope2.scope Then
- fdecl = scope2.scope.FindFuncDecl( IdentLower(),args,,,,,SCOPE_CLASS_HEIRARCHY )
- End If
- Else If static And Not fdecl And Not fixedScope Then
- If _env.classScope() Then
- ' try searching from our class scope
- 'fdecl = _env.classScope().FindFuncDecl( IdentLower(),args )
- If Not fdecl Then
- ' try searching from our class parent scope
- Try
- fdecl = _env.classScope().scope.FindFuncDecl( IdentLower(),args,,,,True,SCOPE_ALL )
- Catch errorMessage:String
- If errorMessage.StartsWith("Compile Error") Then
- Throw errorMessage
- Else
- ' couldn't find an exact match, look elsewhere
- errorDetails = errorMessage
- If Not nearestScopeError And errorDetails.StartsWith("Unable") Then
- nearestScopeError = errorDetails
- End If
- End If
- End Try
- End If
- Else If _env.ModuleScope() Then ' bah
- ' finally, try searching from our module scope
- Try
- fdecl = _env.ModuleScope().FindFuncDecl( IdentLower(),args,,,,True,SCOPE_ALL )
- Catch errorMessage:String
- If errorMessage.StartsWith("Compile Error") Then
- Throw errorMessage
- Else
- ' couldn't find an exact match, look elsewhere
- errorDetails = errorMessage
- If Not nearestScopeError And errorDetails.StartsWith("Unable") Then
- nearestScopeError = errorDetails
- End If
- End If
- End Try
- End If
- End If
- ' couldn't find it? try a global search
- If Not fdecl And Not fixedScope Then
- For Local mdecl:TModuleDecl = EachIn _appInstance.globalImports.Values()
- Try
- fdecl=mdecl.FindFuncDecl( IdentLower(), args,,,,True,SCOPE_ALL )
- Catch errorMessage:String
- If errorMessage.StartsWith("Compile Error") Then
- Throw errorMessage
- Else
- ' couldn't find an exact match, look elsewhere
- errorDetails = errorMessage
- If Not nearestScopeError And errorDetails.StartsWith("Unable") Then
- nearestScopeError = errorDetails
- End If
- End If
- End Try
- If fdecl Exit
- Next
- End If
- 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
- If expr And Not static Then
- Return New TInvokeMemberExpr.Create( expr,fdecl,args ).Semant()
- Else
- If fdecl.IsStatic() And fdecl.IsAbstract() Err "Cannot call abstract " + fdecl.ToString()
- Return New TInvokeExpr.Create( fdecl,args, funcCall ).Semant()
- End If
- 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
- If Not expr Then
- Local ty:TType=scope.FindType( IdentLower(),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
- End If
- If throwError Then
- If nearestScopeError Then
- IdentErr(nearestScopeError)
- Else
- IdentErr(errorDetails)
- End If
- End If
- End Method
- Method SemantScope:TScopeDecl()
- If Not expr Return _env.FindScopeDecl( IdentLower() )
- Local scope:TScopeDecl=expr.SemantScope()
- ' If scope is a namespace, then we are a module. Look up the module id and return it as the real scope.
- If TNamespaceDecl(scope) Then
- Local mdecl:TModuleDecl=TModuleDecl(scope.FindDecl(scope.IdentLower() + "." + IdentLower()))
- If mdecl Then
- Return mdecl
- End If
- End If
- If scope Return scope.FindScopeDecl( IdentLower() )
- End Method
- ' Method Trans$()
- ' Return _trans.TransIdentExpr( Self )
- ' End Method
- End Type
- Type TBuiltinExpr Extends TExpr
- Field id:String
- Field expr:TExpr
- Method Semant:TExpr(options:Int = 0)
- If exprType Return Self
- expr=expr.Semant()
- exprType=expr.exprType
- Return Self
- End Method
- Method Trans$()
- Return _trans.TransBuiltinExpr( Self )
- End Method
- End Type
- Type TLenExpr Extends TBuiltinExpr
- Method Create:TLenExpr( expr:TExpr )
- Self.id="len"
- Self.expr=expr
- Return Self
- End Method
- Method Semant:TExpr(options:Int = 0)
- If exprType Return Self
- expr=expr.Semant()
- ' anything other than a string or array will become "1", and
- ' return a length of 1 accordingly.
- If Not TStringType(expr.exprType) And Not TArrayType(expr.exprType) Then
- expr = New TConstExpr.Create( New TIntType, 1 ).Semant()
- 'this is not useful for numerics
- 'expr = New TConstExpr.Create( TType.stringType, "1" ).Semant()
- _appInstance.mapStringConsts(TConstExpr(expr).value)
- End If
- exprType=New TIntType
- Return Self
- End Method
- Method Copy:TExpr()
- Return New TLenExpr.Create( CopyExpr(expr) )
- End Method
- Method ToString$()
- Return "TLenExpr("+expr.ToString()+")"
- End Method
- End Type
- Type TAscExpr Extends TBuiltinExpr
- Method Create:TAscExpr( expr:TExpr )
- Self.id="asc"
- Self.expr=expr
- Return Self
- End Method
- Method Semant:TExpr(options:Int = 0)
- If exprType Return Self
- If TConstExpr(expr) Then
- Local cexpr:TExpr = New TConstExpr.Create(New TIntType, Asc(TConstExpr(expr).value))
- _appInstance.removeStringConst(TConstExpr(expr).value)
- cexpr.Semant()
- Return cexpr
- End If
-
- expr = expr.SemantAndCast( New TStringType )
- exprType = New TIntType
- Return Self
- End Method
- Method Copy:TExpr()
- Return New TAscExpr.Create( CopyExpr(expr) )
- End Method
- Method ToString$()
- Return "TAscExpr("+expr.ToString()+")"
- End Method
- End Type
- Type TSizeOfExpr Extends TBuiltinExpr
- Method Create:TSizeOfExpr( expr:TExpr )
- Self.id="sizeof"
- Self.expr=expr
- Return Self
- End Method
- Method Semant:TExpr(options:Int = 0)
- If exprType Return Self
- expr=expr.Semant()
- exprType=New TSizeTType
- Return Self
- End Method
- Method Copy:TExpr()
- Return New TSizeOfExpr.Create( CopyExpr(expr) )
- End Method
- Method ToString$()
- Return "TSizeOfExpr("+expr.ToString()+")"
- End Method
- End Type
- Type TChrExpr Extends TBuiltinExpr
- Method Create:TChrExpr( expr:TExpr )
- Self.id="chr"
- Self.expr=expr
- Return Self
- End Method
-
- Method Semant:TExpr(options:Int = 0)
- If exprType Return Self
- If TConstExpr(expr) Then
- Local cexpr:TConstExpr = New TConstExpr.Create(New TStringType, Chr(Int(TConstExpr(expr).value)))
- cexpr.Semant()
- _appInstance.mapStringConsts(cexpr.value)
- Return cexpr
- End If
-
- expr = expr.SemantAndCast( New TIntType )
- exprType = New TStringType
- Return Self
- End Method
- Method Copy:TExpr()
- Return New TChrExpr.Create( CopyExpr(expr) )
- End Method
- Method ToString$()
- Return "TChrExpr("+expr.ToString()+")"
- 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(options:Int = 0)
- args=SemantArgs( args )
- If TIndexExpr(expr) Then
- expr = expr.SemantFunc( args, True, True )
- exprType = expr.exprType
- Return Self
- Else
- Return expr.SemantFunc( args, True, True )
- End If
- End Method
- Method SemantFunc:TExpr( args:TExpr[] , throwError:Int = True, funcCall:Int = False )
- ' we are only likely to be called if a function returns and invokes a function pointer.
- Local ex:TExpr = Semant()
-
- If TFunctionPtrType(ex.exprType) Then
- exprType = TFunctionPtrType(ex.exprType).func.retType
- End If
-
- Self.args = SemantArgs(args)
- expr = ex
-
- Return Self
- End Method
- Method Trans$()
- Return _trans.TransFuncCallExpr( Self )
- End Method
- End Type
- 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(options:Int = 0)
- Err "Syntax error."
- End Method
- Method SemantScope:TScopeDecl()
- Return scope
- End Method
- End Type
- Type TNewExpr Extends TExpr
- Field isSuper:Int
- Field args:TExpr[]
- Field ctor:TFuncDecl
- Method Create:TNewExpr( args:TExpr[]=Null, isSuper:Int = False )
- If args Then
- Self.args=args
- Else
- Self.args = New TExpr[0]
- End If
- Self.isSuper = isSuper
- Return Self
- End Method
- Method Copy:TExpr()
- Return New TNewExpr.Create(CopyArgs(args), isSuper)
- End Method
- Method Semant:TExpr(options:Int = 0)
- Local fdecl:TFuncDecl = _env.FuncScope()
- If Not fdecl Or TNewDecl(fdecl) = Null Or Not _env.ClassScope() Then
- Err "Call to constructor not valid in this context."
- End If
-
- ' must be first statement of New() method
- Local stmt:TStmt = TStmt(fdecl.stmts.First())
-
- If TExprStmt(stmt) = Null Or TExprStmt(stmt).expr <> Self Then
- Err "Call to constructor must be first statement in New()."
- End If
-
- args=SemantArgs( args )
-
- ' validate called constructor
- Try
- Local cDecl:TClassDecl = _env.ClassScope()
- If isSuper Then
- cDecl = cDecl.superClass
- End If
- ctor = cDecl.FindFuncDecl("new",args,,,,True,SCOPE_CLASS_HEIRARCHY )
- Catch errorMessage:String
- If errorMessage.StartsWith("Compile Error") Then
- Throw errorMessage
- Else
- Err errorMessage
- End If
- End Try
-
- ' TODO : expand to full recursive test
- If ctor = fdecl Then
- Err "Recursive constructor invocation."
- End If
-
- ctor.Semant
- args=CastArgs(args, ctor)
-
- ' attach to ctor
- TNewDecl(fdecl).chainedCtor = Self
-
- Return Self
- End Method
- Method Trans$()
- 'Return _trans.TransFuncCallExpr( Self )
- End Method
- End Type
- Type TNullExpr Extends TExpr
- Method Create:TNullExpr(ty:TType)
- exprType = ty
- Return Self
- End Method
- Method Copy:TExpr()
- Return New TNullExpr.Create(exprType)
- End Method
- Method Semant:TExpr(options:Int = 0)
- Return Self
- End Method
- Method Trans$()
- Return "NULL"
- End Method
- Method Eval$()
- Return ""
- End Method
- End Type
- Type TLoopLabelExpr Extends TExpr
- Field loop:TLoopStmt
- Method Create:TLoopLabelExpr(loop:TLoopStmt)
- Self.loop = loop
- Return Self
- End Method
-
- Method Copy:TExpr()
- Return New TLoopLabelExpr.Create(loop)
- End Method
- Method Semant:TExpr(options:Int = 0)
- Return Self
- End Method
- Method Trans$()
- End Method
- Method Eval$()
- Return ""
- End Method
- End Type
- Type TDataLabelExpr Extends TExpr
- Field dataDef:TDefDataDecl
-
- Method Create:TDataLabelExpr(dataDef:TDefDataDecl)
- Self.dataDef = dataDef
- Return Self
- End Method
- Method Copy:TExpr()
- Return New TDataLabelExpr.Create(dataDef)
- End Method
- Method Semant:TExpr(options:Int = 0)
- Return Self
- End Method
- Method Trans$()
- End Method
- Method Eval$()
- Return ""
- End Method
- End Type
- Type TIdentEnumExpr Extends TExpr
- Field value:TEnumValueDecl
- Method Create:TIdentEnumExpr( value:TEnumValueDecl )
- Self.exprType=New TEnumType.Create(TEnumDecl(value.scope))
- Self.value = value
- Return Self
- End Method
- Method Copy:TExpr()
- Return New TIdentEnumExpr.Create( value )
- End Method
- Method Semant:TExpr(options:Int = 0)
- Return Self
- End Method
- Method Trans$()
- Return value.Value()
- End Method
- Method Eval$()
- Return value.Value()
- End Method
- End Type
- Type TStackAllocExpr Extends TBuiltinExpr
- Method Create:TStackAllocExpr( expr:TExpr )
- Self.id="stackalloc"
- Self.expr=expr
- Return Self
- End Method
- Method Semant:TExpr(options:Int = 0)
- If exprType Return Self
- expr = expr.SemantAndCast( New TSizeTType )
- exprType = TType.MapToPointerType(New TByteType)
- Return Self
- End Method
- Method Copy:TExpr()
- Return New TStackAllocExpr.Create( CopyExpr(expr) )
- End Method
- Method ToString$()
- Return "TStackAllocExpr("+expr.ToString()+")"
- End Method
- End Type
- Type TFieldOffsetExpr Extends TBuiltinExpr
- Field typeExpr:TExpr
- Field fieldExpr:TExpr
- Method Create:TFieldOffsetExpr( typeExpr:TExpr, fieldExpr:TExpr )
- Self.id="fieldoffset"
- Self.typeExpr=typeExpr
- Self.fieldExpr = fieldExpr
- Return Self
- End Method
- Method Semant:TExpr(options:Int = 0)
- If exprType Return Self
-
- ' validate type and field
- typeExpr = typeExpr.Semant()
-
- If Not TIdentTypeExpr(typeExpr) Then
- Err "Expecting Type or Struct"
- End If
-
- TIdentExpr(fieldExpr).scope = TIdentTypeExpr(typeExpr).cdecl
- fieldExpr = fieldExpr.Semant()
-
- If Not TVarExpr(fieldExpr) Or Not TFieldDecl(TVarExpr(fieldExpr).decl) Then
- Err "Expecting Field"
- End If
-
- exprType = New TSizeTType
- Return Self
- End Method
- Method Copy:TExpr()
- Return New TFieldOffsetExpr.Create( typeExpr, fieldExpr )
- End Method
- Method ToString$()
- Return "TFieldOffsetExpr("+typeExpr.ToString()+"," + fieldExpr.ToString() + ")"
- End Method
- End Type
|