From rcolebur at SCIRES.COM Sun May 15 05:57:06 2011 From: rcolebur at SCIRES.COM (Coleburn, Randy) Date: Sat, 14 May 2011 23:57:06 -0400 Subject: [M3devel] stubgen problem with m3-tools\m3tk\src\toolmisc\M3Error.m3 line 214 Message-ID: I am seeing a new error when building on Windows 2000, XP, and 7. The error affects at least the following packages: * zeus * obliqrt * obliqparse * juno-app The problem is manifested when running the stub generator (stubgen). In all cases it reports a runtime error, attempt to reference an illegal memory location, and the file and line reference is always to line #214 in m3-tools\m3tk\src\toolmisc\M3Error.m3 I suspect some recent change is the culprit. Here is an example of the error when building juno-app: C:\cm3\bin\stubgen -v1 -sno RemoteView.T -T.M3IMPTAB *** *** runtime error: *** Attempt to reference an illegal memory location. *** file "..\src\toolmisc\M3Error.m3", line 214 *** Stack trace: FP PC Procedure --------- --------- ------------------------------- 0x37f208 0xdd496c CarefulNodeLookup + 0x1e in ..\src\toolmisc\M3Error.m3 0x37f26c 0xdd4401 RecordError + 0x2e8 in ..\src\toolmisc\M3Error.m3 0x37f298 0xdd4026 Report + 0x23 in ..\src\toolmisc\M3Error.m3 0x37f308 0xe46703 Eval + 0x220 in ..\src\sem\M3CExpValue.m3 0x37f358 0xe48773 Set + 0x672 in ..\src\sem\M3CExpValue.m3 0x37f380 0xda645b DoVisit + 0x121 in ..\src\gast\ASTWalk.m3 0x37f3a4 0xe381de Range + 0x85 in ..\src\ast\M3AST_AS_Walk.m3 0x37f3c8 0xda63e8 DoVisit + 0xae in ..\src\gast\ASTWalk.m3 0x37f3ec 0xe36a81 Subrange_type + 0x85 in ..\src\ast\M3AST_AS_Walk.m3 0x37f410 0xda63e8 DoVisit + 0xae in ..\src\gast\ASTWalk.m3 ......... ......... ... more frames ... "C:\cm3\pkg\netobj\src\netobj.tmpl", line 37: quake runtime error: exit 2147483647: C:\cm3\bin\stubgen -v1 -sno RemoteView.T -T.M3IMPTAB --procedure-- -line- -file--- exec -- _v_netobj 37 C:\cm3\pkg\netobj\src\netobj.tmpl netobjv1 44 C:\cm3\pkg\netobj\src\netobj.tmpl netobj 64 C:\cm3\pkg\netobj\src\netobj.tmpl include_dir 105 C:\cm3\Sandbox\m3-ui\juno-2\juno-app\src\m3makefile 4 C:\cm3\Sandbox\m3-ui\juno-2\juno-app\NT386\m3make.args Fatal Error: package build failed WARNING: Encountered an error when processing package "m3-ui\juno-2\juno-app" for "-build". Regards, Randy Coleburn -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Sun May 15 15:46:14 2011 From: hosking at cs.purdue.edu (Tony Hosking) Date: Sun, 15 May 2011 09:46:14 -0400 Subject: [M3devel] stubgen problem with m3-tools\m3tk\src\toolmisc\M3Error.m3 line 214 In-Reply-To: References: Message-ID: There have been recent changes to m3tk. I think by Mika? Sent from my iPad On 14/05/2011, at 11:57 PM, "Coleburn, Randy" wrote: > I am seeing a new error when building on Windows 2000, XP, and 7. > > > > The error affects at least the following packages: > > ? zeus > > ? obliqrt > > ? obliqparse > > ? juno-app > > > > The problem is manifested when running the stub generator (stubgen). In all cases it reports a runtime error, attempt to reference an illegal memory location, and the file and line reference is always to line #214 in m3-tools\m3tk\src\toolmisc\M3Error.m3 > > > > I suspect some recent change is the culprit. > > > > Here is an example of the error when building juno-app: > > > > C:\cm3\bin\stubgen -v1 -sno RemoteView.T -T.M3IMPTAB > > > > > > *** > > *** runtime error: > > *** Attempt to reference an illegal memory location. > > *** file "..\src\toolmisc\M3Error.m3", line 214 > > *** > > > > Stack trace: > > FP PC Procedure > > --------- --------- ------------------------------- > > 0x37f208 0xdd496c CarefulNodeLookup + 0x1e in ..\src\toolmisc\M3Error.m3 > > 0x37f26c 0xdd4401 RecordError + 0x2e8 in ..\src\toolmisc\M3Error.m3 > > 0x37f298 0xdd4026 Report + 0x23 in ..\src\toolmisc\M3Error.m3 > > 0x37f308 0xe46703 Eval + 0x220 in ..\src\sem\M3CExpValue.m3 > > 0x37f358 0xe48773 Set + 0x672 in ..\src\sem\M3CExpValue.m3 > > 0x37f380 0xda645b DoVisit + 0x121 in ..\src\gast\ASTWalk.m3 > > 0x37f3a4 0xe381de Range + 0x85 in ..\src\ast\M3AST_AS_Walk.m3 > > 0x37f3c8 0xda63e8 DoVisit + 0xae in ..\src\gast\ASTWalk.m3 > > 0x37f3ec 0xe36a81 Subrange_type + 0x85 in ..\src\ast\M3AST_AS_Walk.m3 > > 0x37f410 0xda63e8 DoVisit + 0xae in ..\src\gast\ASTWalk.m3 > > ......... ......... ... more frames ... > > "C:\cm3\pkg\netobj\src\netobj.tmpl", line 37: quake runtime error: exit 2147483647: C:\cm3\bin\stubgen -v1 -sno RemoteView.T -T.M3IMPTAB > > > > --procedure-- -line- -file--- > > exec -- > > _v_netobj 37 C:\cm3\pkg\netobj\src\netobj.tmpl > > netobjv1 44 C:\cm3\pkg\netobj\src\netobj.tmpl > > netobj 64 C:\cm3\pkg\netobj\src\netobj.tmpl > > include_dir 105 C:\cm3\Sandbox\m3-ui\juno-2\juno-app\src\m3makefile > > 4 C:\cm3\Sandbox\m3-ui\juno-2\juno-app\NT386\m3make.args > > > > Fatal Error: package build failed > > > > WARNING: Encountered an error when processing package "m3-ui\juno-2\juno-app" for "-build". > > > > Regards, > > Randy Coleburn -------------- next part -------------- An HTML attachment was scrubbed... URL: From rodney_bates at lcwb.coop Sun May 15 19:08:21 2011 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Sun, 15 May 2011 12:08:21 -0500 Subject: [M3devel] stubgen problem with m3-tools\m3tk\src\toolmisc\M3Error.m3 line 214 In-Reply-To: References: Message-ID: <4DD00885.7040006@lcwb.coop> Hmm, I checked in a change to the head on 2011-4-26 that could lie right on this backtrace. It is in M3CExpValue.Eval, and contains a call on M3Error.Report. There are several other calls in M3CExpValue.Eval to M3Error.Report, not involving my change. Simple proportioning between hex displacements and source line counts suggests it is the call in the change. But it is hard to image how my change could do anything but reduce the set of cases where this call is executed, and any such cases remaining sould have been with the same values of all variables, compared to before. Moreover, this or any of the calls in Eval on Report would have been producing error messages before the change. I presume there were no such error messages formerly? Are there any LONGINT literals in the code stubgen is being run on? The change only weakens an overzealous error check for them. On 05/14/2011 10:57 PM, Coleburn, Randy wrote: > I am seeing a new error when building on Windows 2000, XP, and 7. > > The error affects at least the following packages: > > ?zeus > > ?obliqrt > > ?obliqparse > > ?juno-app > > The problem is manifested when running the stub generator (stubgen). In all cases it reports a runtime error, attempt to reference an illegal memory location, and the file and line reference is always to line #*214* in *m3-tools\m3tk\src\toolmisc\M3Error.m3* > > I suspect some recent change is the culprit. > > Here is an example of the error when building juno-app: > > C:\cm3\bin\stubgen -v1 -sno RemoteView.T -T.M3IMPTAB > > *** > > *** runtime error: > > *** Attempt to reference an illegal memory location. > > *** file "..\src\toolmisc\M3Error.m3", line 214 > > *** > > Stack trace: > > FP PC Procedure > > --------- --------- ------------------------------- > > 0x37f208 0xdd496c CarefulNodeLookup + 0x1e in ..\src\toolmisc\M3Error.m3 > > 0x37f26c 0xdd4401 RecordError + 0x2e8 in ..\src\toolmisc\M3Error.m3 > > 0x37f298 0xdd4026 Report + 0x23 in ..\src\toolmisc\M3Error.m3 > > 0x37f308 0xe46703 Eval + 0x220 in ..\src\sem\M3CExpValue.m3 > > 0x37f358 0xe48773 Set + 0x672 in ..\src\sem\M3CExpValue.m3 > > 0x37f380 0xda645b DoVisit + 0x121 in ..\src\gast\ASTWalk.m3 > > 0x37f3a4 0xe381de Range + 0x85 in ..\src\ast\M3AST_AS_Walk.m3 > > 0x37f3c8 0xda63e8 DoVisit + 0xae in ..\src\gast\ASTWalk.m3 > > 0x37f3ec 0xe36a81 Subrange_type + 0x85 in ..\src\ast\M3AST_AS_Walk.m3 > > 0x37f410 0xda63e8 DoVisit + 0xae in ..\src\gast\ASTWalk.m3 > > ......... ......... ... more frames ... > > "C:\cm3\pkg\netobj\src\netobj.tmpl", line 37: quake runtime error: exit 2147483647: C:\cm3\bin\stubgen -v1 -sno RemoteView.T -T.M3IMPTAB > > --procedure-- -line- -file--- > > exec -- > > _v_netobj 37 C:\cm3\pkg\netobj\src\netobj.tmpl > > netobjv1 44 C:\cm3\pkg\netobj\src\netobj.tmpl > > netobj 64 C:\cm3\pkg\netobj\src\netobj.tmpl > > include_dir 105 C:\cm3\Sandbox\m3-ui\juno-2\juno-app\src\m3makefile > > 4 C:\cm3\Sandbox\m3-ui\juno-2\juno-app\NT386\m3make.args > > Fatal Error: package build failed > > WARNING: Encountered an error when processing package "m3-ui\juno-2\juno-app" for "-build". > > Regards, > > Randy Coleburn > From mika at async.caltech.edu Sun May 15 19:23:22 2011 From: mika at async.caltech.edu (Mika Nystrom) Date: Sun, 15 May 2011 10:23:22 -0700 Subject: [M3devel] stubgen problem with m3-tools\m3tk\src\toolmisc\M3Error.m3 line 214 In-Reply-To: <4DD00885.7040006@lcwb.coop> References: <4DD00885.7040006@lcwb.coop> Message-ID: <20110515172322.0D5AC1A2078@async.async.caltech.edu> Stupid question: you did "make clean" (or equivalent) first, right? I've noticed CM3 is pretty bad about detecting changes (at least compared to PM3, which is my basis for all Modula-3 comparisons) and can easily make corrupted binaries if you change things and rely on incremental compilation---at least. if an interface has changed, which I suppose extends to opaque information too. BTW, I have reviewing the LONGINT/m3tk change and Jay's -pthread change on my todo list. CM3 just has been pushed down a bit for a while, hope to get to them soon, not ignoring you guys. Looks to me like something is forgetting to call M3Error.SetCu. Not code I've ever gone near... Mika "Rodney M. Bates" writes: >Hmm, I checked in a change to the head on 2011-4-26 that could lie right on >this backtrace. It is in M3CExpValue.Eval, and contains a call on M3Error.Rep >ort. >There are several other calls in M3CExpValue.Eval to M3Error.Report, not invol >ving >my change. Simple proportioning between hex displacements and source line cou >nts >suggests it is the call in the change. > >But it is hard to image how my change could do anything but reduce the set of >cases where this call is executed, and any such cases remaining sould have bee >n >with the same values of all variables, compared to before. > >Moreover, this or any of the calls in Eval on Report would have been producing >error messages before the change. I presume there were no such error messages >formerly? > >Are there any LONGINT literals in the code stubgen is being run on? The chang >e >only weakens an overzealous error check for them. > >On 05/14/2011 10:57 PM, Coleburn, Randy wrote: >> I am seeing a new error when building on Windows 2000, XP, and 7. >> >> The error affects at least the following packages: >> >> ?zeus >> >> ?obliqrt >> >> ?obliqparse >> >> ?juno-app >> >> The problem is manifested when running the stub generator (stubgen). In all >cases it reports a runtime error, attempt to reference an illegal memory locat >ion, and the file and line reference is always to line #*214* in *m3-tools\m3t >k\src\toolmisc\M3Error.m3* >> >> I suspect some recent change is the culprit. >> >> Here is an example of the error when building juno-app: >> >> C:\cm3\bin\stubgen -v1 -sno RemoteView.T -T.M3IMPTAB >> >> *** >> >> *** runtime error: >> >> *** Attempt to reference an illegal memory location. >> >> *** file "..\src\toolmisc\M3Error.m3", line 214 >> >> *** >> >> Stack trace: >> >> FP PC Procedure >> >> --------- --------- ------------------------------- >> >> 0x37f208 0xdd496c CarefulNodeLookup + 0x1e in ..\src\toolmisc\M3Error.m3 >> >> 0x37f26c 0xdd4401 RecordError + 0x2e8 in ..\src\toolmisc\M3Error.m3 >> >> 0x37f298 0xdd4026 Report + 0x23 in ..\src\toolmisc\M3Error.m3 >> >> 0x37f308 0xe46703 Eval + 0x220 in ..\src\sem\M3CExpValue.m3 >> >> 0x37f358 0xe48773 Set + 0x672 in ..\src\sem\M3CExpValue.m3 >> >> 0x37f380 0xda645b DoVisit + 0x121 in ..\src\gast\ASTWalk.m3 >> >> 0x37f3a4 0xe381de Range + 0x85 in ..\src\ast\M3AST_AS_Walk.m3 >> >> 0x37f3c8 0xda63e8 DoVisit + 0xae in ..\src\gast\ASTWalk.m3 >> >> 0x37f3ec 0xe36a81 Subrange_type + 0x85 in ..\src\ast\M3AST_AS_Walk.m3 >> >> 0x37f410 0xda63e8 DoVisit + 0xae in ..\src\gast\ASTWalk.m3 >> >> ......... ......... ... more frames ... >> >> "C:\cm3\pkg\netobj\src\netobj.tmpl", line 37: quake runtime error: exit 2147 >483647: C:\cm3\bin\stubgen -v1 -sno RemoteView.T -T.M3IMPTAB >> >> --procedure-- -line- -file--- >> >> exec -- >> >> _v_netobj 37 C:\cm3\pkg\netobj\src\netobj.tmpl >> >> netobjv1 44 C:\cm3\pkg\netobj\src\netobj.tmpl >> >> netobj 64 C:\cm3\pkg\netobj\src\netobj.tmpl >> >> include_dir 105 C:\cm3\Sandbox\m3-ui\juno-2\juno-app\src\m3makefile >> >> 4 C:\cm3\Sandbox\m3-ui\juno-2\juno-app\NT386\m3make.args >> >> Fatal Error: package build failed >> >> WARNING: Encountered an error when processing package "m3-ui\juno-2\juno-app >" for "-build". >> >> Regards, >> >> Randy Coleburn >> From rcolebur at SCIRES.COM Sun May 15 23:30:58 2011 From: rcolebur at SCIRES.COM (Coleburn, Randy) Date: Sun, 15 May 2011 17:30:58 -0400 Subject: [M3devel] [M3commit] CVS Update: cm3 In-Reply-To: <20110515210259.1804D24740E9@birch.elegosoft.com> References: <20110515210259.1804D24740E9@birch.elegosoft.com> Message-ID: Rodney: Thanks. I've confirmed that your fix seems to solve the problem. Regards, Randy Coleburn -----Original Message----- From: Rodney M. Bates [mailto:rodney at elego.de] Sent: Sunday, May 15, 2011 7:03 PM To: m3commit at elegosoft.com Subject: [M3commit] CVS Update: cm3 CVSROOT: /usr/cvs Changes by: rodney at birch. 11/05/15 23:02:58 Modified files: cm3/m3-tools/m3tk/src/fe/: M3CGo.m3 Log message: Fix a bug in m3tk that was uncovered by previous fix to LONGINT literal checking, causing NIL deref crashes. M3Go.CompileUnit was failing to call M3Error.SetCu, leaving no current unit for error messages. There are other mysteries here, but this cures the crash and reproduces previous output for at least one case. From rodney_bates at lcwb.coop Mon May 16 14:52:19 2011 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Mon, 16 May 2011 07:52:19 -0500 Subject: [M3devel] stubgen problem with m3-tools\m3tk\src\toolmisc\M3Error.m3 line 214 Message-ID: <4DD11E03.7080502@lcwb.coop> On 05/15/2011 12:23 PM, Mika Nystrom wrote: > Stupid question: > > you did "make clean" (or equivalent) first, right? > > I've noticed CM3 is pretty bad about detecting changes (at least compared > to PM3, which is my basis for all Modula-3 comparisons) and can easily > make corrupted binaries if you change things and rely on incremental > compilation---at least. if an interface has changed, which I suppose > extends to opaque information too. > > BTW, I have reviewing the LONGINT/m3tk change and Jay's -pthread change > on my todo list. CM3 just has been pushed down a bit for a while, hope > to get to them soon, not ignoring you guys. > > Looks to me like something is forgetting to call M3Error.SetCu. Not > code I've ever gone near... Yes, I just found this and checked in a fix in the head. This was a long- standing bug, but was uncovered by my recent change. There is still more to investigate here: - It looks like M3CLex.ReadNumericLiteral is not putting the 'L' into the literal. - It looks like M3CLex.ReadHexDigits won't recognize the 'L' at all, for a based literal. - It looks like somewhere even "0" is getting typed as Longint_literal. As I remember, later processing of LONGINT literals will tolerate the trailing 'L'. > > Mika > > "Rodney M. Bates" writes: >> Hmm, I checked in a change to the head on 2011-4-26 that could lie right on >> this backtrace. It is in M3CExpValue.Eval, and contains a call on M3Error.Rep >> ort. >> There are several other calls in M3CExpValue.Eval to M3Error.Report, not invol >> ving >> my change. Simple proportioning between hex displacements and source line cou >> nts >> suggests it is the call in the change. >> >> But it is hard to image how my change could do anything but reduce the set of >> cases where this call is executed, and any such cases remaining sould have bee >> n >> with the same values of all variables, compared to before. >> >> Moreover, this or any of the calls in Eval on Report would have been producing >> error messages before the change. I presume there were no such error messages >> formerly? >> >> Are there any LONGINT literals in the code stubgen is being run on? The chang >> e >> only weakens an overzealous error check for them. >> >> On 05/14/2011 10:57 PM, Coleburn, Randy wrote: >>> I am seeing a new error when building on Windows 2000, XP, and 7. >>> >>> The error affects at least the following packages: >>> >>> ?zeus >>> >>> ?obliqrt >>> >>> ?obliqparse >>> >>> ?juno-app >>> >>> The problem is manifested when running the stub generator (stubgen). In all >> cases it reports a runtime error, attempt to reference an illegal memory locat >> ion, and the file and line reference is always to line #*214* in *m3-tools\m3t >> k\src\toolmisc\M3Error.m3* >>> >>> I suspect some recent change is the culprit. >>> >>> Here is an example of the error when building juno-app: >>> >>> C:\cm3\bin\stubgen -v1 -sno RemoteView.T -T.M3IMPTAB >>> >>> *** >>> >>> *** runtime error: >>> >>> *** Attempt to reference an illegal memory location. >>> >>> *** file "..\src\toolmisc\M3Error.m3", line 214 >>> >>> *** >>> >>> Stack trace: >>> >>> FP PC Procedure >>> >>> --------- --------- ------------------------------- >>> >>> 0x37f208 0xdd496c CarefulNodeLookup + 0x1e in ..\src\toolmisc\M3Error.m3 >>> >>> 0x37f26c 0xdd4401 RecordError + 0x2e8 in ..\src\toolmisc\M3Error.m3 >>> >>> 0x37f298 0xdd4026 Report + 0x23 in ..\src\toolmisc\M3Error.m3 >>> >>> 0x37f308 0xe46703 Eval + 0x220 in ..\src\sem\M3CExpValue.m3 >>> >>> 0x37f358 0xe48773 Set + 0x672 in ..\src\sem\M3CExpValue.m3 >>> >>> 0x37f380 0xda645b DoVisit + 0x121 in ..\src\gast\ASTWalk.m3 >>> >>> 0x37f3a4 0xe381de Range + 0x85 in ..\src\ast\M3AST_AS_Walk.m3 >>> >>> 0x37f3c8 0xda63e8 DoVisit + 0xae in ..\src\gast\ASTWalk.m3 >>> >>> 0x37f3ec 0xe36a81 Subrange_type + 0x85 in ..\src\ast\M3AST_AS_Walk.m3 >>> >>> 0x37f410 0xda63e8 DoVisit + 0xae in ..\src\gast\ASTWalk.m3 >>> >>> ......... ......... ... more frames ... >>> >>> "C:\cm3\pkg\netobj\src\netobj.tmpl", line 37: quake runtime error: exit 2147 >> 483647: C:\cm3\bin\stubgen -v1 -sno RemoteView.T -T.M3IMPTAB >>> >>> --procedure-- -line- -file--- >>> >>> exec -- >>> >>> _v_netobj 37 C:\cm3\pkg\netobj\src\netobj.tmpl >>> >>> netobjv1 44 C:\cm3\pkg\netobj\src\netobj.tmpl >>> >>> netobj 64 C:\cm3\pkg\netobj\src\netobj.tmpl >>> >>> include_dir 105 C:\cm3\Sandbox\m3-ui\juno-2\juno-app\src\m3makefile >>> >>> 4 C:\cm3\Sandbox\m3-ui\juno-2\juno-app\NT386\m3make.args >>> >>> Fatal Error: package build failed >>> >>> WARNING: Encountered an error when processing package "m3-ui\juno-2\juno-app >> " for "-build". >>> >>> Regards, >>> >>> Randy Coleburn >>> From rodney_bates at lcwb.coop Tue May 17 23:47:08 2011 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Tue, 17 May 2011 16:47:08 -0500 Subject: [M3devel] LONGINT -> more bugs in m3tk In-Reply-To: <4DB6F2B2.3090905@lcwb.coop> References: <20110419115106.7E6A31A207A@async.async.caltech.edu> <4DB6F2B2.3090905@lcwb.coop> Message-ID: <4DD2ECDC.8070806@lcwb.coop> Mika, can you tell me what main program and command you used to get these errors? It would help me to test changes to m3tk. On 04/26/2011 11:28 AM, Rodney M. Bates wrote: > I just checked in a patch tp M3CExpValue.m3 in m3tk, in the head, which I believe will fix this > bug. I compiled it, but have not tested it, as I am sure Mika has this case to retry > more quickly than I can. > > On 04/19/2011 06:51 AM, Mika Nystrom wrote: >> Hello m3devel, >> >> If anyone knows how to fix the following trivially, please go ahead. >> >> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,45: type error in arguments to binary operator >> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,25: bad numeric literal >> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,51: bad numeric literal >> >> (errors reported by m3tk). >> >> The offending line is: >> >> INTERFACE BasicCtypes; >> >> IMPORT Word, Long; >> >> TYPE >> (* the four signed integer types *) >> signed_char = [-16_7f-1 .. 16_7f]; >> short_int = [-16_7fff-1 .. 16_7fff]; >> int = [-16_7fffffff-1 .. 16_7fffffff]; >> long_int = [-16_7fffffffffffffff -1 .. 16_7fffffffffffffff ]; >> long_long = [-16_7fffffffffffffffL-1L .. 16_7fffffffffffffffL]; (** HERE **) >> >> (* the four unsigned integer types *) >> unsigned_char = [16_0 .. 16_ff]; >> unsigned_short_int = [16_0 .. 16_ffff]; >> unsigned_int = [16_0 .. 16_ffffffff]; >> unsigned_long_int = Word.T; >> unsigned_long_long = Long.T; >> >> (* the three floating types *) >> float = REAL; >> double = LONGREAL; >> long_double = EXTENDED; >> >> (* char *) >> char = signed_char; >> >> END BasicCtypes. >> >> I'll look at it myself, but not immediately (no time). Workaround for now. >> >> Mika >> > From mika at async.caltech.edu Wed May 18 03:35:42 2011 From: mika at async.caltech.edu (Mika Nystrom) Date: Tue, 17 May 2011 18:35:42 -0700 Subject: [M3devel] LONGINT -> more bugs in m3tk In-Reply-To: <4DD2ECDC.8070806@lcwb.coop> References: <20110419115106.7E6A31A207A@async.async.caltech.edu> <4DB6F2B2.3090905@lcwb.coop> <4DD2ECDC.8070806@lcwb.coop> Message-ID: <20110518013542.194111A2078@async.async.caltech.edu> I think you'll get that error if you run stubgen on anything that references a type from BasicCtypes (e.g., int, char_star ...) I'm pretty sure I actually got it running the stub generator for my Scheme interpreter, which I have posted links to here a few times, but I haven't had time to push into CM3 yet. Mika "Rodney M. Bates" writes: >Mika, can you tell me what main program and command you used to get these erro >rs? >It would help me to test changes to m3tk. > >On 04/26/2011 11:28 AM, Rodney M. Bates wrote: >> I just checked in a patch tp M3CExpValue.m3 in m3tk, in the head, which I be >lieve will fix this >> bug. I compiled it, but have not tested it, as I am sure Mika has this case >to retry >> more quickly than I can. >> >> On 04/19/2011 06:51 AM, Mika Nystrom wrote: >>> Hello m3devel, >>> >>> If anyone knows how to fix the following trivially, please go ahead. >>> >>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,45: type e >rror in arguments to binary operator >>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,25: bad nu >meric literal >>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,51: bad nu >meric literal >>> >>> (errors reported by m3tk). >>> >>> The offending line is: >>> >>> INTERFACE BasicCtypes; >>> >>> IMPORT Word, Long; >>> >>> TYPE >>> (* the four signed integer types *) >>> signed_char = [-16_7f-1 .. 16_7f]; >>> short_int = [-16_7fff-1 .. 16_7fff]; >>> int = [-16_7fffffff-1 .. 16_7fffffff]; >>> long_int = [-16_7fffffffffffffff -1 .. 16_7fffffffffffffff ]; >>> long_long = [-16_7fffffffffffffffL-1L .. 16_7fffffffffffffffL]; (** HERE ** >) >>> >>> (* the four unsigned integer types *) >>> unsigned_char = [16_0 .. 16_ff]; >>> unsigned_short_int = [16_0 .. 16_ffff]; >>> unsigned_int = [16_0 .. 16_ffffffff]; >>> unsigned_long_int = Word.T; >>> unsigned_long_long = Long.T; >>> >>> (* the three floating types *) >>> float = REAL; >>> double = LONGREAL; >>> long_double = EXTENDED; >>> >>> (* char *) >>> char = signed_char; >>> >>> END BasicCtypes. >>> >>> I'll look at it myself, but not immediately (no time). Workaround for now. >>> >>> Mika >>> >> From rcolebur at SCIRES.COM Wed May 18 20:27:44 2011 From: rcolebur at SCIRES.COM (Coleburn, Randy) Date: Wed, 18 May 2011 14:27:44 -0400 Subject: [M3devel] LONGINT -> more bugs in m3tk In-Reply-To: <20110518013542.194111A2078@async.async.caltech.edu> References: <20110419115106.7E6A31A207A@async.async.caltech.edu> <4DB6F2B2.3090905@lcwb.coop> <4DD2ECDC.8070806@lcwb.coop> <20110518013542.194111A2078@async.async.caltech.edu> Message-ID: While we are on the subject of the stub generator, there is another long-standing problem. I've submitted this one years ago and I think I still have the example program I devised to show it. So, I'll try to dig this up and put it into the bug tracker. The basic situation is that there are cases where the stub generator doesn't generate imports for all interfaces needed by the resulting stub. You can work around this problem by manually editing the generated stub to provide the missing imports, but this gets old quickly. I'll send a follow-up post with the details once I find them in my archives. Regards, Randy Coleburn -----Original Message----- From: Mika Nystrom [mailto:mika at async.caltech.edu] Sent: Tuesday, May 17, 2011 9:36 PM To: Rodney M. Bates Cc: m3devel at elegosoft.com Subject: Re: [M3devel] LONGINT -> more bugs in m3tk I think you'll get that error if you run stubgen on anything that references a type from BasicCtypes (e.g., int, char_star ...) I'm pretty sure I actually got it running the stub generator for my Scheme interpreter, which I have posted links to here a few times, but I haven't had time to push into CM3 yet. Mika "Rodney M. Bates" writes: >Mika, can you tell me what main program and command you used to get these erro >rs? >It would help me to test changes to m3tk. > >On 04/26/2011 11:28 AM, Rodney M. Bates wrote: >> I just checked in a patch tp M3CExpValue.m3 in m3tk, in the head, which I be >lieve will fix this >> bug. I compiled it, but have not tested it, as I am sure Mika has this case >to retry >> more quickly than I can. >> >> On 04/19/2011 06:51 AM, Mika Nystrom wrote: >>> Hello m3devel, >>> >>> If anyone knows how to fix the following trivially, please go ahead. >>> >>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,45: type e >rror in arguments to binary operator >>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,25: bad nu >meric literal >>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,51: bad nu >meric literal >>> >>> (errors reported by m3tk). >>> >>> The offending line is: >>> >>> INTERFACE BasicCtypes; >>> >>> IMPORT Word, Long; >>> >>> TYPE >>> (* the four signed integer types *) >>> signed_char = [-16_7f-1 .. 16_7f]; >>> short_int = [-16_7fff-1 .. 16_7fff]; >>> int = [-16_7fffffff-1 .. 16_7fffffff]; >>> long_int = [-16_7fffffffffffffff -1 .. 16_7fffffffffffffff ]; >>> long_long = [-16_7fffffffffffffffL-1L .. 16_7fffffffffffffffL]; (** HERE ** >) >>> >>> (* the four unsigned integer types *) >>> unsigned_char = [16_0 .. 16_ff]; >>> unsigned_short_int = [16_0 .. 16_ffff]; >>> unsigned_int = [16_0 .. 16_ffffffff]; >>> unsigned_long_int = Word.T; >>> unsigned_long_long = Long.T; >>> >>> (* the three floating types *) >>> float = REAL; >>> double = LONGREAL; >>> long_double = EXTENDED; >>> >>> (* char *) >>> char = signed_char; >>> >>> END BasicCtypes. >>> >>> I'll look at it myself, but not immediately (no time). Workaround for now. >>> >>> Mika >>> >> From rcolebur at SCIRES.COM Wed May 18 23:04:41 2011 From: rcolebur at SCIRES.COM (Coleburn, Randy) Date: Wed, 18 May 2011 17:04:41 -0400 Subject: [M3devel] LONGINT -> more bugs in m3tk In-Reply-To: References: <20110419115106.7E6A31A207A@async.async.caltech.edu> <4DB6F2B2.3090905@lcwb.coop> <4DD2ECDC.8070806@lcwb.coop> <20110518013542.194111A2078@async.async.caltech.edu> Message-ID: Ok, I found some stuff in my archives about a set of documented stubgen problems, but this stuff doesn't include the problem I described with the failure to generate imports for all interfaces. Actually, I think this interface import problem is with the network objects stub generator, so I will either find or create an example of this problem and submit later. Here is a short program (with comments) that demonstrates some stubgen problems. I generated this program back in January 2001, so these are long-standing issues. Regards, Randy Coleburn m3makefile is: import("libm3") import("netobj") Interface("StubGenProblem") Netobj("StubGenProblem", "T") Library("NetObjProblem") StubGenProblem.i3 is: INTERFACE StubGenProblem; (* Interface demonstrating problem with Network Objects Stub Generator *) (* R.C.Coleburn, 01/24/2001 *) IMPORT NetObj, Thread; TYPE MyRecord = RECORD a: INTEGER := 0; b: TEXT := "zero"; END; CONST Default = MyRecord{1, "one"}; TYPE MyObject = OBJECT myRec: MyRecord := Default; (* if you change above line to be: myRec: MyRecord; that is, leave out the default initializer, the stub generator no longer complains when parameters of type MyObject are passed to methods of type T. *) END; TYPE T = NetObj.T OBJECT METHODS (* method testA is accepted by the NetObj Stub Generator *) testA(myRec: MyRecord) RAISES {NetObj.Error, Thread.Alerted}; (* method testB is accepted by the NetObj Stub Generator *) testB(myRec: MyRecord := Default) RAISES {NetObj.Error, Thread.Alerted}; (* method testC yeilds the following error from the NetObj Stub Generator: stubgen: INTERNAL ERROR: AstToVal.ProcessExp: unsupported value *) (* Does anyone know why the stub generator can't handle this? *) (* Does anyone know of a workaround or a fix to the stub generator? *) testC(myObj: MyObject) RAISES {NetObj.Error, Thread.Alerted}; (* BTW, if you comment out the assignment of Default to MyObject.myRec in the declaration on line 16, the stub generator no longer complains. So, it seems that the problem is passing an object parameter containing a record field member with a default initializer. Note that passing a record parameter with a default initializer is not a problem for the stub generator. *) END; END StubGenProblem. -----Original Message----- From: Coleburn, Randy Sent: Wednesday, May 18, 2011 2:28 PM To: Mika Nystrom; Rodney M. Bates Cc: m3devel at elegosoft.com Subject: Re: [M3devel] LONGINT -> more bugs in m3tk While we are on the subject of the stub generator, there is another long-standing problem. I've submitted this one years ago and I think I still have the example program I devised to show it. So, I'll try to dig this up and put it into the bug tracker. The basic situation is that there are cases where the stub generator doesn't generate imports for all interfaces needed by the resulting stub. You can work around this problem by manually editing the generated stub to provide the missing imports, but this gets old quickly. I'll send a follow-up post with the details once I find them in my archives. Regards, Randy Coleburn From dabenavidesd at yahoo.es Wed May 18 23:49:05 2011 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Wed, 18 May 2011 22:49:05 +0100 (BST) Subject: [M3devel] LONGINT -> more bugs in m3tk In-Reply-To: Message-ID: <846840.19495.qm@web29712.mail.ird.yahoo.com> Hi all: This is good news (though old) shows up, this is perhaps the problem with Obliq problem (worked in pm3), by the way what could be missing if so from there in CM3? Thanks in advance PS It might be that CM3 once worked Obliq, since there is a thesis reportedly working on Obliq3D of Blair MacIntyre, an augmented reality system, this is probably 1999, so a lot of stuff might came or not after that. --- El mi?, 18/5/11, Coleburn, Randy escribi?: > De: Coleburn, Randy > Asunto: Re: [M3devel] LONGINT -> more bugs in m3tk > Para: "m3devel at elegosoft.com" > Fecha: mi?rcoles, 18 de mayo, 2011 16:04 > Ok, I found some stuff in my archives > about a set of documented stubgen problems, but this stuff > doesn't include the problem I described with the failure to > generate imports for all interfaces. Actually, I think > this interface import problem is with the network objects > stub generator, so I will either find or create an example > of this problem and submit later. > > Here is a short program (with comments) that demonstrates > some stubgen problems. I generated this program back > in January 2001, so these are long-standing issues. > > Regards, > Randy Coleburn > > > m3makefile is: > > import("libm3") > import("netobj") > Interface("StubGenProblem") > Netobj("StubGenProblem", "T") > Library("NetObjProblem") > > > > StubGenProblem.i3 is: > > INTERFACE StubGenProblem; > (* Interface demonstrating problem with Network Objects > Stub Generator *) > (* R.C.Coleburn, 01/24/2001 *) > IMPORT > NetObj, > Thread; > TYPE > MyRecord = RECORD > a: INTEGER := 0; > b: TEXT := "zero"; > END; > CONST > Default = MyRecord{1, "one"}; > TYPE > MyObject = OBJECT > myRec: MyRecord := Default; > (* if you change above line to be: > myRec: MyRecord; > that is, leave out > the default initializer, the stub > generator no longer > complains when parameters of type > MyObject are passed > to methods of type T. *) > END; > TYPE > T = NetObj.T OBJECT > METHODS > (* method testA is accepted by the > NetObj Stub Generator *) > testA(myRec: MyRecord) RAISES > {NetObj.Error, Thread.Alerted}; > > (* method testB is accepted by the > NetObj Stub Generator *) > testB(myRec: MyRecord := Default) > RAISES {NetObj.Error, Thread.Alerted}; > > (* method testC yeilds the following > error from the NetObj Stub Generator: > stubgen: INTERNAL > ERROR: AstToVal.ProcessExp: unsupported value *) > (* Does anyone know why the stub > generator can't handle this? *) > (* Does anyone know of a workaround or > a fix to the stub generator? *) > testC(myObj: MyObject) RAISES > {NetObj.Error, Thread.Alerted}; > > (* BTW, if you comment out the > assignment of Default to MyObject.myRec > in the declaration on line 16, the > stub generator no longer complains. > So, it seems that the problem is > passing an object parameter containing > a record field member with a default > initializer. Note that passing a > record parameter with a default > initializer is not a problem for the > stub generator. *) > END; > END StubGenProblem. > > > > -----Original Message----- > From: Coleburn, Randy > Sent: Wednesday, May 18, 2011 2:28 PM > To: Mika Nystrom; Rodney M. Bates > Cc: m3devel at elegosoft.com > Subject: Re: [M3devel] LONGINT -> more bugs in m3tk > > While we are on the subject of the stub generator, there is > another long-standing problem. > > I've submitted this one years ago and I think I still have > the example program I devised to show it. > > So, I'll try to dig this up and put it into the bug > tracker. > > The basic situation is that there are cases where the stub > generator doesn't generate imports for all interfaces needed > by the resulting stub. You can work around this > problem by manually editing the generated stub to provide > the missing imports, but this gets old quickly. > > I'll send a follow-up post with the details once I find > them in my archives. > > Regards, > Randy Coleburn > From mika at async.caltech.edu Thu May 19 01:38:58 2011 From: mika at async.caltech.edu (Mika Nystrom) Date: Wed, 18 May 2011 16:38:58 -0700 Subject: [M3devel] LONGINT -> more bugs in m3tk In-Reply-To: References: <20110419115106.7E6A31A207A@async.async.caltech.edu> <4DB6F2B2.3090905@lcwb.coop> <4DD2ECDC.8070806@lcwb.coop> <20110518013542.194111A2078@async.async.caltech.edu> Message-ID: <20110518233858.545FB1A2078@async.async.caltech.edu> Ah, ok... such bugs ought to be fairly easy to fix. Maybe... To be clear, there are at least three stub generators that use m3tk that I know of (and probably others too) "stubgen" for Network Objects "stablegen" for some sort of stable storage database "sstubgen" (not in CM3 yet!) that generates stubs for the "Modula-Scheme system" (what I referenced below) Mika "Coleburn, Randy" writes: >While we are on the subject of the stub generator, there is another long-st= >anding problem. > >I've submitted this one years ago and I think I still have the example prog= >ram I devised to show it. > >So, I'll try to dig this up and put it into the bug tracker. > >The basic situation is that there are cases where the stub generator doesn'= >t generate imports for all interfaces needed by the resulting stub. You ca= >n work around this problem by manually editing the generated stub to provid= >e the missing imports, but this gets old quickly. > >I'll send a follow-up post with the details once I find them in my archives= >. > >Regards, >Randy Coleburn > >-----Original Message----- >From: Mika Nystrom [mailto:mika at async.caltech.edu]=20 >Sent: Tuesday, May 17, 2011 9:36 PM >To: Rodney M. Bates >Cc: m3devel at elegosoft.com >Subject: Re: [M3devel] LONGINT -> more bugs in m3tk > >I think you'll get that error if you run stubgen on anything that reference= >s >a type from BasicCtypes (e.g., int, char_star ...) > >I'm pretty sure I actually got it running the stub generator for my >Scheme interpreter, which I have posted links to here a few times, but I >haven't had time to push into CM3 yet. > > Mika > >"Rodney M. Bates" writes: >>Mika, can you tell me what main program and command you used to get these = >erro >>rs? >>It would help me to test changes to m3tk. >> >>On 04/26/2011 11:28 AM, Rodney M. Bates wrote: >>> I just checked in a patch tp M3CExpValue.m3 in m3tk, in the head, which = >I be >>lieve will fix this >>> bug. I compiled it, but have not tested it, as I am sure Mika has this c= >ase=20 >>to retry >>> more quickly than I can. >>> >>> On 04/19/2011 06:51 AM, Mika Nystrom wrote: >>>> Hello m3devel, >>>> >>>> If anyone knows how to fix the following trivially, please go ahead. >>>> >>>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,45: ty= >pe e >>rror in arguments to binary operator >>>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,25: ba= >d nu >>meric literal >>>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,51: ba= >d nu >>meric literal >>>> >>>> (errors reported by m3tk). >>>> >>>> The offending line is: >>>> >>>> INTERFACE BasicCtypes; >>>> >>>> IMPORT Word, Long; >>>> >>>> TYPE >>>> (* the four signed integer types *) >>>> signed_char =3D [-16_7f-1 .. 16_7f]; >>>> short_int =3D [-16_7fff-1 .. 16_7fff]; >>>> int =3D [-16_7fffffff-1 .. 16_7fffffff]; >>>> long_int =3D [-16_7fffffffffffffff -1 .. 16_7fffffffffffffff ]; >>>> long_long =3D [-16_7fffffffffffffffL-1L .. 16_7fffffffffffffffL]; (** H= >ERE ** >>) >>>> >>>> (* the four unsigned integer types *) >>>> unsigned_char =3D [16_0 .. 16_ff]; >>>> unsigned_short_int =3D [16_0 .. 16_ffff]; >>>> unsigned_int =3D [16_0 .. 16_ffffffff]; >>>> unsigned_long_int =3D Word.T; >>>> unsigned_long_long =3D Long.T; >>>> >>>> (* the three floating types *) >>>> float =3D REAL; >>>> double =3D LONGREAL; >>>> long_double =3D EXTENDED; >>>> >>>> (* char *) >>>> char =3D signed_char; >>>> >>>> END BasicCtypes. >>>> >>>> I'll look at it myself, but not immediately (no time). Workaround for n= >ow. >>>> >>>> Mika >>>> >>> From rodney_bates at lcwb.coop Wed May 18 23:41:31 2011 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Wed, 18 May 2011 16:41:31 -0500 Subject: [M3devel] LONGINT -> more bugs in m3tk In-Reply-To: <20110518013542.194111A2078@async.async.caltech.edu> References: <20110419115106.7E6A31A207A@async.async.caltech.edu> <4DB6F2B2.3090905@lcwb.coop> <4DD2ECDC.8070806@lcwb.coop> <20110518013542.194111A2078@async.async.caltech.edu> Message-ID: <4DD43D0B.6080400@lcwb.coop> Thanks. That got me going. On 05/17/2011 08:35 PM, Mika Nystrom wrote: > I think you'll get that error if you run stubgen on anything that references > a type from BasicCtypes (e.g., int, char_star ...) > > I'm pretty sure I actually got it running the stub generator for my > Scheme interpreter, which I have posted links to here a few times, but I > haven't had time to push into CM3 yet. > > Mika > > "Rodney M. Bates" writes: >> Mika, can you tell me what main program and command you used to get these erro >> rs? >> It would help me to test changes to m3tk. >> >> On 04/26/2011 11:28 AM, Rodney M. Bates wrote: >>> I just checked in a patch tp M3CExpValue.m3 in m3tk, in the head, which I be >> lieve will fix this >>> bug. I compiled it, but have not tested it, as I am sure Mika has this case >> to retry >>> more quickly than I can. >>> >>> On 04/19/2011 06:51 AM, Mika Nystrom wrote: >>>> Hello m3devel, >>>> >>>> If anyone knows how to fix the following trivially, please go ahead. >>>> >>>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,45: type e >> rror in arguments to binary operator >>>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,25: bad nu >> meric literal >>>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,51: bad nu >> meric literal >>>> >>>> (errors reported by m3tk). >>>> >>>> The offending line is: >>>> >>>> INTERFACE BasicCtypes; >>>> >>>> IMPORT Word, Long; >>>> >>>> TYPE >>>> (* the four signed integer types *) >>>> signed_char = [-16_7f-1 .. 16_7f]; >>>> short_int = [-16_7fff-1 .. 16_7fff]; >>>> int = [-16_7fffffff-1 .. 16_7fffffff]; >>>> long_int = [-16_7fffffffffffffff -1 .. 16_7fffffffffffffff ]; >>>> long_long = [-16_7fffffffffffffffL-1L .. 16_7fffffffffffffffL]; (** HERE ** >> ) >>>> >>>> (* the four unsigned integer types *) >>>> unsigned_char = [16_0 .. 16_ff]; >>>> unsigned_short_int = [16_0 .. 16_ffff]; >>>> unsigned_int = [16_0 .. 16_ffffffff]; >>>> unsigned_long_int = Word.T; >>>> unsigned_long_long = Long.T; >>>> >>>> (* the three floating types *) >>>> float = REAL; >>>> double = LONGREAL; >>>> long_double = EXTENDED; >>>> >>>> (* char *) >>>> char = signed_char; >>>> >>>> END BasicCtypes. >>>> >>>> I'll look at it myself, but not immediately (no time). Workaround for now. >>>> >>>> Mika >>>> >>> > From rodney_bates at lcwb.coop Thu May 19 17:41:15 2011 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Thu, 19 May 2011 10:41:15 -0500 Subject: [M3devel] missing libm3/src/types Message-ID: <4DD53A1B.3030805@lcwb.coop> What happened to cm3/m3-libs/libm3/src/types and its contents in the head? They all are gone, but cm3/m3-libs/libm3/src/m3makefile contains include_dir ("types"), and libm3 won't build: rodney at allegheny:~/proj/m3/cm3-new/cm3/scripts$ ./do-pkg.sh build libm3 /home/rodney/proj/m3/cm3-new/cm3/scripts/pkgmap.sh -c "cm3 -build -override $RARGS -DROOT='/home/rodney/proj/m3/cm3-new/cm3' " libm3 === package /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3 === +++ cm3 -build -override $RARGS -DROOT='/home/rodney/proj/m3/cm3-new/cm3' +++ --- building in AMD64_LINUX --- "/home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/m3makefile", line 27: quake runtime error: unable to open "/home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/types/m3makefile" for reading --procedure-- -line- -file--- include_dir -- include_dir 27 /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/m3makefile 6 /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/AMD64_LINUX/m3make.args Fatal Error: package build failed ==> /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3 done rodney at allegheny:~/proj/m3/cm3-new/cm3/scripts$ It looks like either types needs to come back, or include_dir ("types") needs to go away, but which? If somebody knows, it would save a lot of time poking around. From hosking at cs.purdue.edu Thu May 19 17:45:59 2011 From: hosking at cs.purdue.edu (Tony Hosking) Date: Thu, 19 May 2011 11:45:59 -0400 Subject: [M3devel] missing libm3/src/types In-Reply-To: <4DD53A1B.3030805@lcwb.coop> References: <4DD53A1B.3030805@lcwb.coop> Message-ID: <3169D748-68A3-4A9A-A582-60C68D32AB94@cs.purdue.edu> Moved to m3core. There shouldn't be anything in libm3/types. On May 19, 2011, at 11:41 AM, Rodney M. Bates wrote: > What happened to cm3/m3-libs/libm3/src/types and its contents in the head? > They all are gone, but cm3/m3-libs/libm3/src/m3makefile contains > include_dir ("types"), and libm3 won't build: > > > rodney at allegheny:~/proj/m3/cm3-new/cm3/scripts$ ./do-pkg.sh build libm3 > /home/rodney/proj/m3/cm3-new/cm3/scripts/pkgmap.sh -c "cm3 -build -override $RARGS -DROOT='/home/rodney/proj/m3/cm3-new/cm3' " libm3 > === package /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3 === > +++ cm3 -build -override $RARGS -DROOT='/home/rodney/proj/m3/cm3-new/cm3' +++ > --- building in AMD64_LINUX --- > > "/home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/m3makefile", line 27: quake runtime error: unable to open "/home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/types/m3makefile" for reading > > --procedure-- -line- -file--- > include_dir -- > include_dir 27 /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/m3makefile > 6 /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/AMD64_LINUX/m3make.args > > Fatal Error: package build failed > ==> /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3 done > > rodney at allegheny:~/proj/m3/cm3-new/cm3/scripts$ > > It looks like either types needs to come back, or include_dir ("types") needs to go away, > but which? If somebody knows, it would save a lot of time poking around. From hosking at cs.purdue.edu Thu May 19 17:51:36 2011 From: hosking at cs.purdue.edu (Tony Hosking) Date: Thu, 19 May 2011 11:51:36 -0400 Subject: [M3devel] missing libm3/src/types In-Reply-To: <3169D748-68A3-4A9A-A582-60C68D32AB94@cs.purdue.edu> References: <4DD53A1B.3030805@lcwb.coop> <3169D748-68A3-4A9A-A582-60C68D32AB94@cs.purdue.edu> Message-ID: <55EDF7AD-B04C-48DF-9266-7A3B3A61CDCF@cs.purdue.edu> Actually, looks like Jay tried to restore LongrealType and RealType for Mika. Clients should really be adjusted to include: IMPORT LongFloat as LongrealType, RealFloat as RealType; On May 19, 2011, at 11:45 AM, Tony Hosking wrote: > Moved to m3core. There shouldn't be anything in libm3/types. > > On May 19, 2011, at 11:41 AM, Rodney M. Bates wrote: > >> What happened to cm3/m3-libs/libm3/src/types and its contents in the head? >> They all are gone, but cm3/m3-libs/libm3/src/m3makefile contains >> include_dir ("types"), and libm3 won't build: >> >> >> rodney at allegheny:~/proj/m3/cm3-new/cm3/scripts$ ./do-pkg.sh build libm3 >> /home/rodney/proj/m3/cm3-new/cm3/scripts/pkgmap.sh -c "cm3 -build -override $RARGS -DROOT='/home/rodney/proj/m3/cm3-new/cm3' " libm3 >> === package /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3 === >> +++ cm3 -build -override $RARGS -DROOT='/home/rodney/proj/m3/cm3-new/cm3' +++ >> --- building in AMD64_LINUX --- >> >> "/home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/m3makefile", line 27: quake runtime error: unable to open "/home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/types/m3makefile" for reading >> >> --procedure-- -line- -file--- >> include_dir -- >> include_dir 27 /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/m3makefile >> 6 /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/AMD64_LINUX/m3make.args >> >> Fatal Error: package build failed >> ==> /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3 done >> >> rodney at allegheny:~/proj/m3/cm3-new/cm3/scripts$ >> >> It looks like either types needs to come back, or include_dir ("types") needs to go away, >> but which? If somebody knows, it would save a lot of time poking around. > From dabenavidesd at yahoo.es Thu May 19 18:18:20 2011 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Thu, 19 May 2011 17:18:20 +0100 (BST) Subject: [M3devel] missing libm3/src/types In-Reply-To: <3169D748-68A3-4A9A-A582-60C68D32AB94@cs.purdue.edu> Message-ID: <321796.84407.qm@web29715.mail.ird.yahoo.com> Hi all: if it could affect the compiler usage if in fact such usage why would one give such types inside cm3 or m3build process aside of m3core, I mean the top hierarchy must be primitive types at bottom then refs, objects, etc or reverse, and its type rules besides modules and interfaces, perhaps a good example would be to see the interfaces of Modula-2+ Vulcan system, since it had everything compiled cached and managed to survive even crashes and bridge everything to the Vesta CM system, quick large compilations, see: http://www-cs-faculty.stanford.edu/~eroberts/cv.html An advanced system to type check may require quick timely access to large nodes since type inference is something very dependent on its size, a bigger tree a bigger problem, even if ever get to compile type inferencing (an Obliq prototype already done), but many modules around would be like dancing in hard feet over sized. Thanks in advance --- El jue, 19/5/11, Tony Hosking escribi?: > De: Tony Hosking > Asunto: Re: [M3devel] missing libm3/src/types > Para: "Rodney M. Bates" > CC: "m3devel" > Fecha: jueves, 19 de mayo, 2011 10:45 > Moved to m3core. There > shouldn't be anything in libm3/types. > > On May 19, 2011, at 11:41 AM, Rodney M. Bates wrote: > > > What happened to cm3/m3-libs/libm3/src/types and its > contents in the head? > > They all are gone, but > cm3/m3-libs/libm3/src/m3makefile contains > > include_dir ("types"), and libm3 won't build: > > > > > > rodney at allegheny:~/proj/m3/cm3-new/cm3/scripts$ > ./do-pkg.sh build libm3 > > /home/rodney/proj/m3/cm3-new/cm3/scripts/pkgmap.sh -c > "cm3 -build -override $RARGS > -DROOT='/home/rodney/proj/m3/cm3-new/cm3' " libm3 > > === package > /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3 === > > +++ cm3 -build -override $RARGS > -DROOT='/home/rodney/proj/m3/cm3-new/cm3' +++ > > --- building in AMD64_LINUX --- > > > > > "/home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/m3makefile", > line 27: quake runtime error: unable to open > "/home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/types/m3makefile" > for reading > > > > --procedure-- -line- -file--- > > include_dir -- > > > include_dir 27 > /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/m3makefile > > > 6 > /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/AMD64_LINUX/m3make.args > > > > Fatal Error: package build failed > > ==> /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3 > done > > > > rodney at allegheny:~/proj/m3/cm3-new/cm3/scripts$ > > > > It looks like either types needs to come back, or > include_dir ("types") needs to go away, > > but which? If somebody knows, it would save a > lot of time poking around. > > From jay.krell at cornell.edu Sun May 22 10:26:30 2011 From: jay.krell at cornell.edu (Jay K) Date: Sun, 22 May 2011 08:26:30 +0000 Subject: [M3devel] range analysis? Message-ID: I've been sitting on this diff a long while. In some places the frontend knows the bounds of a type/value and will optimize away range checks. I'm pretty sure. This makes it do that more. I haven't looked at or tested this in ages. But the basic idea seems sound, simple, easy enough to get a few small wins from. For example if you have: a: [-10..-1]; b: [1..10]; then all comparisons between a and b are compile-time constant. Comparisons of cardinals to negative numbers, likewise. One thing maybe missing below is handling of empty ranges like a: [1..-1]; The code assumes the minimum of a type is less than or equal to its maximum. Index: m3-sys/m3front/src/misc/CG.i3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.i3,v retrieving revision 1.15 diff -r1.15 CG.i3 11c11 < IMPORT Target, M3CG, M3; --- > IMPORT Target, M3CG, M3, TInt; 402c402,406 < PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type); --- > PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type; > min_valid: BOOLEAN := FALSE; > max_valid: BOOLEAN := FALSE; > min: Target.Int := TInt.Zero; > max: Target.Int := TInt.Zero); 414,415c418,423 < PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0); < (* == Load (v, o, t.size, t.align, t) *) --- > PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0; > min_valid: BOOLEAN := FALSE; > max_valid: BOOLEAN := FALSE; > min: Target.Int := TInt.Zero; > max: Target.Int := TInt.Zero); > (* == Load (v, o, t.size, t.align, t, min/max...) *) Index: m3-sys/m3front/src/misc/CG.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.m3,v retrieving revision 1.40 diff -r1.40 CG.m3 13c13 < IMPORT M3, M3CG, M3CG_Ops, M3CG_Check; --- > IMPORT M3, M3CG, M3CG_Ops, M3CG_Check, RTIO, RTParams; 45a46,49 > min_valid : BOOLEAN := FALSE; (* whether or not min is valid *) > max_valid : BOOLEAN := FALSE; (* whether or not max is valid *) > min : Target.Int := TInt.Zero; (* the minimum possible value *) > max : Target.Int := TInt.Zero; (* the maximum possible value *) 80c84,85 < VAR --- > VAR > debug := FALSE; 604a610,614 > v.min := TInt.Zero; > v.max := TInt.Zero; > v.min_valid := FALSE; > v.max_valid := FALSE; > 766a777,780 > x.min := TInt.Zero; > x.max := TInt.Zero; > x.min_valid := FALSE; > x.max_valid := FALSE; 978a993,995 > IF debug THEN > RTIO.PutText("m3front:cg:Init_int:NOT in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); > END; 980a998,1001 > END; > > IF debug THEN > RTIO.PutText("m3front:cg:Init_int:in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); 1266c1287,1291 < PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type) = --- > PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type; > min_valid: BOOLEAN := FALSE; > max_valid: BOOLEAN := FALSE; > min: Target.Int := TInt.Zero; > max: Target.Int := TInt.Zero) = 1276c1301 < SimpleLoad (v, o, t); --- > SimpleLoad (v, o, t, min_valid, max_valid, min, max); 1291c1316 < SimpleLoad (v, o, best_type); --- > SimpleLoad (v, o, best_type, min_valid, max_valid, min, max); 1312c1337,1341 < PROCEDURE SimpleLoad (v: Var; o: Offset; t: Type) = --- > PROCEDURE SimpleLoad (v: Var; o: Offset; t: Type; > min_valid: BOOLEAN := FALSE; > max_valid: BOOLEAN := FALSE; > min: Target.Int := TInt.Zero; > max: Target.Int := TInt.Zero) = 1323a1353,1356 > x.min_valid := min_valid; > x.max_valid := max_valid; > x.min := min; > x.max := max; 1339a1373,1376 > x.min := TInt.Zero; > x.max := TInt.Zero; > x.min_valid := FALSE; > x.max_valid := FALSE; 1347a1385,1388 > stack[tos-1].min := TInt.Zero; > stack[tos-1].max := TInt.Zero; > stack[tos-1].min_valid := FALSE; > stack[tos-1].max_valid := FALSE; 1350c1391,1395 < PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0) = --- > PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0; > min_valid: BOOLEAN := FALSE; > max_valid: BOOLEAN := FALSE; > min: Target.Int := TInt.Zero; > max: Target.Int := TInt.Zero) = 1352c1397 < SimpleLoad (v, o, t); --- > SimpleLoad (v, o, t, min_valid, max_valid, min, max); 1815a1861,1864 > x.min_valid := TRUE; > x.max_valid := TRUE; > x.min := i; > x.max := i; 1832,1834c1881,2007 < BEGIN < IF Force_pair (commute := TRUE) THEN < op := M3CG.SwappedCompare [op]; --- > VAR always_true: BOOLEAN; > always_false: BOOLEAN; > left_type: Type; > right_type: Type; > left_min: Target.Int; > left_max: Target.Int; > right_min: Target.Int; > right_max: Target.Int; > left_signed: BOOLEAN; > right_signed: BOOLEAN; > BEGIN > > always_true := FALSE; > always_false := FALSE; > > WITH left = stack [SCheck (2, "Compare-left")], > right = stack [SCheck (1, "Compare-right")] DO > > left_type := left.type; > right_type := right.type; > > IF left.min_valid > AND left.max_valid > AND right.min_valid > AND right.max_valid > AND Target.OrdinalType[left_type] > AND Target.OrdinalType[right_type] THEN > > left_min := left.min; > left_max := left.max; > right_min := right.min; > right_max := right.max; > left_signed := Target.SignedType[left_type]; > right_signed := Target.SignedType[right_type]; > > (* First handle types that match in signedness. *) > > IF left_signed = right_signed THEN > > (* Check for ranges with no overlap. *) > > IF left_signed (* and right_signed *) THEN > IF TInt.LT(left_max, right_min) THEN > always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; > ELSIF TInt.GT(left_min, right_max) THEN > always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; > END; > ELSE (* left_signed and right_signed both false *) > IF TWord.LT(left_max, right_min) THEN > always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; > ELSIF TWord.GT(left_min, right_max) THEN > always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; > END; > END; > > (* Check for overlap just on the edge, e.g. [0..1] compared to [1..2]. *) > > IF NOT (always_true OR always_false) THEN > IF TInt.EQ(left_max, right_min) THEN > always_true := op = Cmp.LE; > always_false := op = Cmp.GT; > ELSIF TInt.EQ(left_min, right_max) THEN > always_true := op = Cmp.GE; > always_false := op = Cmp.LT; > END; > END; > > (* Handle equal subranges with one element, not likely to occur. *) > > IF NOT (always_true OR always_false) THEN > IF TInt.EQ(left_max, left_min) > AND TInt.EQ(left_max, right_max) > AND TInt.EQ(left_max, right_min) THEN > always_true := op IN SET OF Cmp{Cmp.GE, Cmp.LE, Cmp.EQ}; > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.GT, Cmp.NE}; > END; > END; > ELSE > > (* Now deal with mixed up types (signed compared to unsigned). > * We may be able to merge these by setting some min/max > * to zero. That is, the minimum of an unsigned type is zero. > * However we want to be sure not to interpret unsigned min/max > * as signed. > *) > > IF left_signed THEN > IF TInt.LT(left_max, TInt.Zero) THEN > always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; > ELSIF TInt.EQ(left_max, TInt.Zero) THEN > always_true := op = Cmp.LE; > always_false := op = Cmp.GT; > END; > ELSE (* right is signed *) > IF TInt.LT(right_max, TInt.Zero) THEN > always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; > ELSIF TInt.EQ(right_max, TInt.Zero) THEN > always_true := op = Cmp.GE; > always_false := op = Cmp.LT; > END; > END; > END; > END; > > <* ASSERT NOT (always_true AND always_false) *> > > IF always_true OR always_false THEN > Discard(right_type); > Discard(left_type); > IF always_true THEN > cg.load_integer (Target.Integer.cg_type, TInt.One); > ELSE > cg.load_integer (Target.Integer.cg_type, TInt.Zero); > END > ELSE > IF Force_pair (commute := TRUE) THEN > op := M3CG.SwappedCompare [op]; > END; > cg.compare (t, Target.Integer.cg_type, op); > SPop (2, "Compare"); > END; 1836,1837d2008 < cg.compare (t, Target.Integer.cg_type, op); < SPop (2, "Compare"); 2880a3052,3055 > x.min := TInt.Zero; > x.max := TInt.Zero; > x.min_valid := FALSE; > x.max_valid := FALSE; 2977c3152,3153 < BEGIN --- > BEGIN > debug := debug OR RTParams.IsPresent ("m3front_cg_debug"); Index: m3-sys/m3front/src/values/Variable.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/values/Variable.m3,v retrieving revision 1.13 diff -r1.13 Variable.m3 362a363,365 > VAR min: Target.Int; > max: Target.Int; > bounds_valid: BOOLEAN; 395c398,401 < CG.Load (t.cg_var, t.offset, t.size, t.cg_align, t.stk_type); --- > (*GetBounds (t, min, max); > bounds_valid := TInt.LE(min, max);*) > bounds_valid := t.tipe # NIL AND Type.GetBounds(t.tipe, min, max) AND TInt.LE(min, max); > CG.Load (t.cg_var, t.offset, t.size, t.cg_align, t.stk_type, bounds_valid, bounds_valid, min, max); -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Sun May 22 10:58:50 2011 From: jay.krell at cornell.edu (Jay K) Date: Sun, 22 May 2011 08:58:50 +0000 Subject: [M3devel] thread tester on 32bit Windows Message-ID: I'm not sure if I posted this. This is on Windows XP. C:\dev2\cm3.2\m3-libs\m3core\tests\thread>\bin\x86\cdb NT386\threadtest.exe @M3paranoidgc Microsoft (R) Windows Debugger Version 6.11.0001.404 X86 Copyright (c) Microsoft Corporation. All rights reserved. CommandLine: NT386\threadtest.exe @M3paranoidgc Symbol search path is: SRV*C:\symbols*http://msdl.microsoft.com/download/symbols Executable search path is: ModLoad: 00400000 00c7b000 threadtest.exe ModLoad: 7c900000 7c9b2000 ntdll.dll ModLoad: 7c800000 7c8f6000 C:\WINDOWS2\system32\kernel32.dll ModLoad: 78520000 785c3000 C:\WINDOWS2\WinSxS\x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.30729.4974_x-ww_d889290f\MSVCR90.dll (6ec.1010): Break instruction exception - code 80000003 (first chance) eax=00251eb4 ebx=7ffdf000 ecx=00000005 edx=00000020 esi=00251f48 edi=00251eb4 eip=7c90120e esp=0012fb20 ebp=0012fc94 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202 ntdll!DbgBreakPoint: 7c90120e cc int 3 0:000> .lines Line number information will be loaded 0:000> g Writing file...done Creating read threads...done Creating fork threads...done Creating alloc threads...done Creating lock threads...done running...printing oldest/median age/newest .(6ec.116c): Access violation - code c0000005 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=001ffffc ebx=00200000 ecx=00000002 edx=004317f0 esi=00380018 edi=00380018 eip=0043181c esp=0117fb98 ebp=0117fbc0 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010202 threadtest!RTCollector__RefSanityCheck+0x2c: 0043181c 8b18 mov ebx,dword ptr [eax] ds:0023:001ffffc=???????? 0:005> db @eax 001ffffc ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 0020000c ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 0020001c ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 0020002c ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 0020003c ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 0020004c ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 0020005c ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 0020006c ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 0:005> ~*k 0 Id: 6ec.1010 Suspend: 2 Teb: 7ffde000 Unfrozen ChildEBP RetAddr 0012fcd8 7c90d21a ntdll!KiFastSystemCallRet 0012fcdc 7c8023f1 ntdll!NtDelayExecution+0xc 0012fd34 7c802455 kernel32!SleepEx+0x61 0012fd44 0042bd6e kernel32!Sleep+0xf 0012fd84 0042bb47 threadtest!ThreadWin32__XPause+0x1c7 [..\src\thread\WIN32\ThreadWin32.m3 @ 765] 0012fda8 00404870 threadtest!Thread__Pause+0x31 [..\src\thread\WIN32\ThreadWin32.m3 @ 727] 0012fee4 00426c95 threadtest!Main_M3+0x13e2 [..\src\Main.m3 @ 558] 0012ff28 00426262 threadtest!RTLinker__RunMainBody+0x250 [..\src\runtime\common\RTLinker.m3 @ 406] 0012ff40 00426306 threadtest!RTLinker__AddUnitI+0xf7 [..\src\runtime\common\RTLinker.m3 @ 113] 0012ff60 00401038 threadtest!RTLinker__AddUnit+0x9c [..\src\runtime\common\RTLinker.m3 @ 122] 0012ff7c 00462900 threadtest!main+0x38 [_m3main.mc @ 4] 0012ffc0 7c817077 threadtest!__tmainCRTStartup+0x10f [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 582] 0012fff0 00000000 kernel32!BaseProcessStart+0x23 1 Id: 6ec.1168 Suspend: 2 Teb: 7ffdd000 Unfrozen ChildEBP RetAddr 00d7fc64 7c90df5a ntdll!KiFastSystemCallRet 00d7fc68 7c919b23 ntdll!NtWaitForSingleObject+0xc 00d7fcf0 7c901046 ntdll!RtlpWaitForCriticalSection+0x132 00d7fcf8 0042a153 ntdll!RtlEnterCriticalSection+0x46 00d7fd30 0042a830 threadtest!ThreadWin32__InitCondition+0xa1 [..\src\thread\WIN32\ThreadWin32.m3 @ 186] 00d7fd50 0042cc08 threadtest!Thread__Broadcast+0x3f [..\src\thread\WIN32\ThreadWin32.m3 @ 409] 00d7fd6c 004295f9 threadtest!RTOS__UnlockHeap+0xb3 [..\src\thread\WIN32\ThreadWin32.m3 @ 1181] 00d7fd88 00429586 threadtest!RTAllocator_M3_LINE_370+0x15 [..\src\runtime\common\RTAllocator.m3 @ 371] 00d7fdc8 00428ba8 threadtest!RTAllocator__AllocTraced+0x105 [..\src\runtime\common\RTAllocator.m3 @ 368] 00d7fdfc 004286dc threadtest!RTAllocator__GetTracedObj+0x86 [..\src\runtime\common\RTAllocator.m3 @ 224] 00d7fe18 00408679 threadtest!RTHooks__AllocateTracedObj+0x15 [..\src\runtime\common\RTAllocator.m3 @ 122] 00d7fe40 00401360 threadtest!FileRd__Open+0x19 [..\src\rw\FileRd.m3 @ 16] 00d7ff78 0042b5ff threadtest!Main__RApply+0x160 [..\src\Main.m3 @ 182] 00d7ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ThreadWin32.m3 @ 615] 00d7ffec 00000000 kernel32!BaseThreadStart+0x37 2 Id: 6ec.1174 Suspend: 2 Teb: 7ffdc000 Unfrozen ChildEBP RetAddr 00e7fc64 7c90df5a ntdll!KiFastSystemCallRet 00e7fc68 7c919b23 ntdll!NtWaitForSingleObject+0xc 00e7fcf0 7c901046 ntdll!RtlpWaitForCriticalSection+0x132 00e7fcf8 0042a153 ntdll!RtlEnterCriticalSection+0x46 00e7fd30 0042a830 threadtest!ThreadWin32__InitCondition+0xa1 [..\src\thread\WIN32\ThreadWin32.m3 @ 186] 00e7fd50 0042cc08 threadtest!Thread__Broadcast+0x3f [..\src\thread\WIN32\ThreadWin32.m3 @ 409] 00e7fd6c 004295f9 threadtest!RTOS__UnlockHeap+0xb3 [..\src\thread\WIN32\ThreadWin32.m3 @ 1181] 00e7fd88 00429586 threadtest!RTAllocator_M3_LINE_370+0x15 [..\src\runtime\common\RTAllocator.m3 @ 371] 00e7fdc8 00428ba8 threadtest!RTAllocator__AllocTraced+0x105 [..\src\runtime\common\RTAllocator.m3 @ 368] 00e7fdfc 004286dc threadtest!RTAllocator__GetTracedObj+0x86 [..\src\runtime\common\RTAllocator.m3 @ 224] 00e7fe18 00408679 threadtest!RTHooks__AllocateTracedObj+0x15 [..\src\runtime\common\RTAllocator.m3 @ 122] 00e7fe40 00401360 threadtest!FileRd__Open+0x19 [..\src\rw\FileRd.m3 @ 16] 00e7ff78 0042b5ff threadtest!Main__RApply+0x160 [..\src\Main.m3 @ 182] 00e7ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ThreadWin32.m3 @ 615] 00e7ffec 00000000 kernel32!BaseThreadStart+0x37 3 Id: 6ec.14cc Suspend: 2 Teb: 7ffdb000 Unfrozen ChildEBP RetAddr 00f7fd1c 7c90d0ba ntdll!KiFastSystemCallRet 00f7fd20 7c8109b6 ntdll!NtCreateFile+0xc 00f7fdb8 7c801a53 kernel32!CreateFileW+0x35f 00f7fddc 00417f10 kernel32!CreateFileA+0x30 00f7fe18 00408689 threadtest!FS__OpenFileReadonly+0x3c [..\src\os\WIN32\FSWin32.m3 @ 226] 00f7fe40 00401360 threadtest!FileRd__Open+0x29 [..\src\rw\FileRd.m3 @ 16] 00f7ff78 0042b5ff threadtest!Main__RApply+0x160 [..\src\Main.m3 @ 182] 00f7ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ ThreadWin32.m3 @ 615] 00f7ffec 00000000 kernel32!BaseThreadStart+0x37 4 Id: 6ec.d20 Suspend: 2 Teb: 7ffda000 Unfrozen ChildEBP RetAddr 0107fcf8 7c90df5a ntdll!KiFastSystemCallRet 0107fcfc 7c919b23 ntdll!NtWaitForSingleObject+0xc 0107fd84 7c901046 ntdll!RtlpWaitForCriticalSection+0x132 0107fd8c 0042cb42 ntdll!RtlEnterCriticalSection+0x46 0107fda0 0042954e threadtest!RTOS__LockHeap+0x2c [..\src\thread\WIN32\ThreadWin32.m3 @ 1168] 0107fde0 00428ba8 threadtest!RTAllocator__AllocTraced+0xcd [..\src\runtime\common\RTAllocator.m3 @ 367] 0107fe14 004286dc threadtest!RTAllocator__GetTracedObj+0x86 [..\src\runtime\common\RTAllocator.m3 @ 224] 0107fe30 00452f79 threadtest!RTHooks__AllocateTracedObj+0x15 [..\src\runtime\common\RTAllocator.m3 @ 122] 0107fe4c 0043e62a threadtest!Text8CString__New+0x19 [..\src\text\Text8CString.m3 @ 17] 0107fe64 0043cdf3 threadtest!M3toC__StoT+0x16 [..\src\C\Common\M3toC.m3 @ 96] 0107fe90 0040d037 threadtest!RTArgs__GetArg+0x6e [..\src\runtime\WIN32\RTArgs.m3 @ 139] 0107feb8 00401d6a threadtest!Params__Get+0x57 [..\src\params\Params.m3 @ 18] 0107ff78 0042b5ff threadtest!Main__FApply+0x141 [..\src\Main.m3 @ 245] 0107ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ThreadWin32.m3 @ 615] 0107ffec 00000000 kernel32!BaseThreadStart+0x37 # 5 Id: 6ec.116c Suspend: 1 Teb: 7ffd9000 Unfrozen ChildEBP RetAddr 0117fbc0 0044fbdc threadtest!RTCollector__RefSanityCheck+0x2c [..\src\runtime\common\RTCollector.m3 @ 1702] 0117fc04 0044f4df threadtest!RTHeapMap__Walk+0x448 [..\src\runtime\common\RTHeapMap.m3 @ 202] 0117fc28 0044f4ba threadtest!RTHeapMap__DoWalkRef+0x62 [..\src\runtime\common\RTHeapMap.m3 @ 62] 0117fc4c 0044f4ba threadtest!RTHeapMap__DoWalkRef+0x3d [..\src\runtime\common\RTHeapMap.m3 @ 57] 0117fc70 0044f475 threadtest!RTHeapMap__DoWalkRef+0x3d [..\src\runtime\common\RTHeapMap.m3 @ 57] 0117fc9c 00431607 threadtest!RTHeapMap__WalkRef+0xf5 [..\src\runtime\common\RTHeapMap.m3 @ 47] 0117fcd8 0044eab4 threadtest!RTCollector__SanityCheck+0x23c [..\src\runtime\common\RTCollector.m3 @ 1660] 0117fcf8 0042f379 threadtest!RTHeapRep__InvokeMonitors+0x84 [..\src\runtime\common\RTHeapRep.m3 @ 56] 0117fd4c 0042f15e threadtest!RTCollector__CollectSomeInStateZero+0x1e0 [..\src\runtime\common\RTCollector.m3 @ 786] 0117fd5c 0042edfc threadtest!RTCollector__CollectSome+0x6e [..\src\runtime\common\RTCollector.m3 @ 720] 0117fda0 00429554 threadtest!RTHeapRep__CollectEnough+0x9b [..\src\runtime\common\RTCollector.m3 @ 655] 0117fde0 00428ba8 threadtest!RTAllocator__AllocTraced+0xd3 [..\src\runtime\common\RTAllocator.m3 @ 368] 0117fe14 004286dc threadtest!RTAllocator__GetTracedObj+0x86 [..\src\runtime\common\RTAllocator.m3 @ 224] 0117fe30 00452f79 threadtest!RTHooks__AllocateTracedObj+0x15 [..\src\runtime\common\RTAllocator.m3 @ 122] 0117fe4c 0043e62a threadtest!Text8CString__New+0x19 [..\src\text\Text8CString.m3 @ 17] 0117fe64 0043cdf3 threadtest!M3toC__StoT+0x16 [..\src\C\Common\M3toC.m3 @ 96] 0117fe90 0040d037 threadtest!RTArgs__GetArg+0x6e [..\src\runtime\WIN32\RTArgs.m3 @ 139] 0117feb8 00401d6a threadtest!Params__Get+0x57 [..\src\params\Params.m3 @ 18] 0117ff78 0042b5ff threadtest!Main__FApply+0x141 [..\src\Main.m3 @ 245] 0117ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ThreadWin32.m3 @ 615] 6 Id: 6ec.11b4 Suspend: 2 Teb: 7ffd8000 Unfrozen ChildEBP RetAddr 0127fcf8 7c90df5a ntdll!KiFastSystemCallRet 0127fcfc 7c919b23 ntdll!NtWaitForSingleObject+0xc 0127fd84 7c901046 ntdll!RtlpWaitForCriticalSection+0x132 0127fd8c 0042cb42 ntdll!RtlEnterCriticalSection+0x46 0127fda0 0042954e threadtest!RTOS__LockHeap+0x2c [..\src\thread\WIN32\ThreadWin32.m3 @ 1168] 0127fde0 00428ba8 threadtest!RTAllocator__AllocTraced+0xcd [..\src\runtime\common\RTAllocator.m3 @ 367] 0127fe14 004286dc threadtest!RTAllocator__GetTracedObj+0x86 [..\src\runtime\common\RTAllocator.m3 @ 224] 0127fe30 00452f79 threadtest!RTHooks__AllocateTracedObj+0x15 [..\src\runtime\common\RTAllocator.m3 @ 122] 0127fe4c 0043e62a threadtest!Text8CString__New+0x19 [..\src\text\Text8CString.m3 @ 17] 0127fe64 0043cdf3 threadtest!M3toC__StoT+0x16 [..\src\C\Common\M3toC.m3 @ 96] 0127fe90 0040d037 threadtest!RTArgs__GetArg+0x6e [..\src\runtime\WIN32\RTArgs.m3 @ 139] 0127feb8 00401d6a threadtest!Params__Get+0x57 [..\src\params\Params.m3 @ 18] 0127ff78 0042b5ff threadtest!Main__FApply+0x141 [..\src\Main.m3 @ 245] 0127ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ThreadWin32.m3 @ 615] 0127ffec 00000000 kernel32!BaseThreadStart+0x37 7 Id: 6ec.1038 Suspend: 2 Teb: 7ffd7000 Unfrozen ChildEBP RetAddr 0137fdd4 7c90df5a ntdll!KiFastSystemCallRet 0137fdd8 7c919b23 ntdll!NtWaitForSingleObject+0xc 0137fe60 7c901046 ntdll!RtlpWaitForCriticalSection+0x132 0137fe68 0042cb42 ntdll!RtlEnterCriticalSection+0x46 0137fe7c 0042954e threadtest!RTOS__LockHeap+0x2c [..\src\thread\WIN32\ThreadWin32.m3 @ 1168] 0137febc 004290fd threadtest!RTAllocator__AllocTraced+0xcd [..\src\runtime\common\RTAllocator.m3 @ 367] 0137fef8 00428788 threadtest!RTAllocator__GetOpenArray+0x91 [..\src\runtime\common\RTAllocator.m3 @ 296] 0137ff1c 00402430 threadtest!RTHooks__AllocateOpenArray+0x19 [..\src\runtime\common\RTAllocator.m3 @ 143] 0137ff78 0042b5ff threadtest!Main__AApply+0x128 [..\src\Main.m3 @ 283] 0137ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ThreadWin32.m3 @ 615] 0137ffec 00000000 kernel32!BaseThreadStart+0x37 8 Id: 6ec.1034 Suspend: 2 Teb: 7ffd6000 Unfrozen ChildEBP RetAddr 0147fdd4 7c90df5a ntdll!KiFastSystemCallRet 0147fdd8 7c919b23 ntdll!NtWaitForSingleObject+0xc 0147fe60 7c901046 ntdll!RtlpWaitForCriticalSection+0x132 0147fe68 0042cb42 ntdll!RtlEnterCriticalSection+0x46 0147fe7c 0042954e threadtest!RTOS__LockHeap+0x2c [..\src\thread\WIN32\ThreadWin32.m3 @ 1168] 0147febc 004290fd threadtest!RTAllocator__AllocTraced+0xcd [..\src\runtime\common\RTAllocator.m3 @ 367] 0147fef8 00428788 threadtest!RTAllocator__GetOpenArray+0x91 [..\src\runtime\common\RTAllocator.m3 @ 296] 0147ff1c 00402430 threadtest!RTHooks__AllocateOpenArray+0x19 [..\src\runtime\common\RTAllocator.m3 @ 143] 0147ff78 0042b5ff threadtest!Main__AApply+0x128 [..\src\Main.m3 @ 283] 0147ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ThreadWin32.m3 @ 615] 0147ffec 00000000 kernel32!BaseThreadStart+0x37 9 Id: 6ec.10d0 Suspend: 2 Teb: 7ffd5000 Unfrozen ChildEBP RetAddr 0157fdd4 7c90df5a ntdll!KiFastSystemCallRet 0157fdd8 7c919b23 ntdll!NtWaitForSingleObject+0xc 0157fe60 7c901046 ntdll!RtlpWaitForCriticalSection+0x132 0157fe68 0042cb42 ntdll!RtlEnterCriticalSection+0x46 0157fe7c 0042954e threadtest!RTOS__LockHeap+0x2c [..\src\thread\WIN32\ThreadWin32.m3 @ 1168] 0157febc 004290fd threadtest!RTAllocator__AllocTraced+0xcd [..\src\runtime\common\RTAllocator.m3 @ 367] 0157fef8 00428788 threadtest!RTAllocator__GetOpenArray+0x91 [..\src\runtime\common\RTAllocator.m3 @ 296] 0157ff1c 00402430 threadtest!RTHooks__AllocateOpenArray+0x19 [..\src\runtime\common\RTAllocator.m3 @ 143] 0157ff78 0042b5ff threadtest!Main__AApply+0x128 [..\src\Main.m3 @ 283] 0157ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ThreadWin32.m3 @ 615] 0157ffec 00000000 kernel32!BaseThreadStart+0x37 10 Id: 6ec.ff8 Suspend: 2 Teb: 7ffd4000 Unfrozen ChildEBP RetAddr 0167fe48 7c90df5a ntdll!KiFastSystemCallRet 0167fe4c 7c919b23 ntdll!NtWaitForSingleObject+0xc 0167fed4 7c901046 ntdll!RtlpWaitForCriticalSection+0x132 0167fedc 00429f52 ntdll!RtlEnterCriticalSection+0x46 0167ff10 0042a287 threadtest!ThreadWin32__InitMutex+0x53 [..\src\thread\WIN32\ThreadWin32.m3 @ 148] 0167ff28 00402a5f threadtest!ThreadWin32__LockMutex+0x3f [..\src\thread\WIN32\ThreadWin32.m3 @ 210] 0167ff78 0042b5ff threadtest!Main__LApply+0x15f [..\src\Main.m3 @ 319] 0167ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ThreadWin32.m3 @ 615] 0167ffec 00000000 kernel32!BaseThreadStart+0x37 11 Id: 6ec.10e8 Suspend: 2 Teb: 7ffaf000 Unfrozen ChildEBP RetAddr 0177fdfc 7c90df5a ntdll!KiFastSystemCallRet 0177fe00 7c919b23 ntdll!NtWaitForSingleObject+0xc 0177fe88 7c901046 ntdll!RtlpWaitForCriticalSection+0x132 0177fe90 0042cb42 ntdll!RtlEnterCriticalSection+0x46 0177fea4 004332ce threadtest!RTOS__LockHeap+0x2c [..\src\thread\WIN32\ThreadWin2.m3 @ 1168] 0177fed8 00429faf threadtest!RTHeapRep__RegisterFinalCleanup+0x73 [..\src\runtime\common\RTCollector.m3 @ 2150] 0177ff10 0042a287 threadtest!ThreadWin32__InitMutex+0xb0 [..\src\thread\WIN32\ThreadWin32.m3 @ 156] 0177ff28 00402a5f threadtest!ThreadWin32__LockMutex+0x3f [..\src\thread\WIN32\ThreadWin32.m3 @ 210] 0177ff78 0042b5ff threadtest!Main__LApply+0x15f [..\src\Main.m3 @ 319] 0177ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ThreadWin32.m3 @ 615] 0177ffec 00000000 kernel32!BaseThreadStart+0x37 12 Id: 6ec.10d8 Suspend: 2 Teb: 7ffae000 Unfrozen ChildEBP RetAddr 0187fe48 7c90df5a ntdll!KiFastSystemCallRet 0187fe4c 7c919b23 ntdll!NtWaitForSingleObject+0xc 0187fed4 7c901046 ntdll!RtlpWaitForCriticalSection+0x132 0187fedc 00429f52 ntdll!RtlEnterCriticalSection+0x46 0187ff10 0042a287 threadtest!ThreadWin32__InitMutex+0x53 [..\src\thread\WIN32\ThreadWin32.m3 @ 148] 0187ff28 00402a5f threadtest!ThreadWin32__LockMutex+0x3f [..\src\thread\WIN32\ThreadWin32.m3 @ 210] 0187ff78 0042b5ff threadtest!Main__LApply+0x15f [..\src\Main.m3 @ 319] 0187ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ThreadWin32.m3 @ 615] 0187ffec 00000000 kernel32!BaseThreadStart+0x37 0:005> I suspect more logging/tracing is needed, to see what was moved where. - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Sun May 22 20:51:08 2011 From: hosking at cs.purdue.edu (Tony Hosking) Date: Sun, 22 May 2011 14:51:08 -0400 Subject: [M3devel] range analysis? In-Reply-To: References: Message-ID: <7FF8F0BA-AEC4-40DB-98A0-E1206985A72E@cs.purdue.edu> This is problematic. On May 22, 2011, at 4:26 AM, Jay K wrote: > The code assumes the minimum of a type is less than or equal to its maximum. -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Sun May 22 20:51:59 2011 From: hosking at cs.purdue.edu (Tony Hosking) Date: Sun, 22 May 2011 14:51:59 -0400 Subject: [M3devel] range analysis? In-Reply-To: References: Message-ID: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> So, one question is: what benefit does this really give? Your examples seem a little contrived. On May 22, 2011, at 4:26 AM, Jay K wrote: > I've been sitting on this diff a long while. > > In some places the frontend knows the bounds of a type/value and > will optimize away range checks. I'm pretty sure. > > > > This makes it do that more. > > > I haven't looked at or tested this in ages. > But the basic idea seems sound, simple, easy enough to get a few small wins from. > > For example if you have: > > a: [-10..-1]; > b: [1..10]; > > then all comparisons between a and b are compile-time constant. > > Comparisons of cardinals to negative numbers, likewise. > > One thing maybe missing below is handling of empty ranges like > a: [1..-1]; > > The code assumes the minimum of a type is less than or equal to its maximum. > > > Index: m3-sys/m3front/src/misc/CG.i3 > =================================================================== > RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.i3,v > retrieving revision 1.15 > diff -r1.15 CG.i3 > 11c11 > < IMPORT Target, M3CG, M3; > --- > > IMPORT Target, M3CG, M3, TInt; > 402c402,406 > < PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type); > --- > > PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type; > > min_valid: BOOLEAN := FALSE; > > max_valid: BOOLEAN := FALSE; > > min: Target.Int := TInt.Zero; > > max: Target.Int := TInt.Zero); > 414,415c418,423 > < PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0); > < (* == Load (v, o, t.size, t.align, t) *) > --- > > PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0; > > min_valid: BOOLEAN := FALSE; > > max_valid: BOOLEAN := FALSE; > > min: Target.Int := TInt.Zero; > > max: Target.Int := TInt.Zero); > > (* == Load (v, o, t.size, t.align, t, min/max...) *) > Index: m3-sys/m3front/src/misc/CG.m3 > =================================================================== > RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.m3,v > retrieving revision 1.40 > diff -r1.40 CG.m3 > 13c13 > < IMPORT M3, M3CG, M3CG_Ops, M3CG_Check; > --- > > IMPORT M3, M3CG, M3CG_Ops, M3CG_Check, RTIO, RTParams; > 45a46,49 > > min_valid : BOOLEAN := FALSE; (* whether or not min is valid *) > > max_valid : BOOLEAN := FALSE; (* whether or not max is valid *) > > min : Target.Int := TInt.Zero; (* the minimum possible value *) > > max : Target.Int := TInt.Zero; (* the maximum possible value *) > 80c84,85 > < VAR > --- > > VAR > > debug := FALSE; > 604a610,614 > > v.min := TInt.Zero; > > v.max := TInt.Zero; > > v.min_valid := FALSE; > > v.max_valid := FALSE; > > > 766a777,780 > > x.min := TInt.Zero; > > x.max := TInt.Zero; > > x.min_valid := FALSE; > > x.max_valid := FALSE; > 978a993,995 > > IF debug THEN > > RTIO.PutText("m3front:cg:Init_int:NOT in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); > > END; > 980a998,1001 > > END; > > > > IF debug THEN > > RTIO.PutText("m3front:cg:Init_int:in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); > 1266c1287,1291 > < PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type) = > --- > > PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type; > > min_valid: BOOLEAN := FALSE; > > max_valid: BOOLEAN := FALSE; > > min: Target.Int := TInt.Zero; > > max: Target.Int := TInt.Zero) = > 1276c1301 > < SimpleLoad (v, o, t); > --- > > SimpleLoad (v, o, t, min_valid, max_valid, min, max); > 1291c1316 > < SimpleLoad (v, o, best_type); > --- > > SimpleLoad (v, o, best_type, min_valid, max_valid, min, max); > 1312c1337,1341 > < PROCEDURE SimpleLoad (v: Var; o: Offset; t: Type) = > --- > > PROCEDURE SimpleLoad (v: Var; o: Offset; t: Type; > > min_valid: BOOLEAN := FALSE; > > max_valid: BOOLEAN := FALSE; > > min: Target.Int := TInt.Zero; > > max: Target.Int := TInt.Zero) = > 1323a1353,1356 > > x.min_valid := min_valid; > > x.max_valid := max_valid; > > x.min := min; > > x.max := max; > 1339a1373,1376 > > x.min := TInt.Zero; > > x.max := TInt.Zero; > > x.min_valid := FALSE; > > x.max_valid := FALSE; > 1347a1385,1388 > > stack[tos-1].min := TInt.Zero; > > stack[tos-1].max := TInt.Zero; > > stack[tos-1].min_valid := FALSE; > > stack[tos-1].max_valid := FALSE; > 1350c1391,1395 > < PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0) = > --- > > PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0; > > min_valid: BOOLEAN := FALSE; > > max_valid: BOOLEAN := FALSE; > > min: Target.Int := TInt.Zero; > > max: Target.Int := TInt.Zero) = > 1352c1397 > < SimpleLoad (v, o, t); > --- > > SimpleLoad (v, o, t, min_valid, max_valid, min, max); > 1815a1861,1864 > > x.min_valid := TRUE; > > x.max_valid := TRUE; > > x.min := i; > > x.max := i; > 1832,1834c1881,2007 > < BEGIN > < IF Force_pair (commute := TRUE) THEN > < op := M3CG.SwappedCompare [op]; > --- > > VAR always_true: BOOLEAN; > > always_false: BOOLEAN; > > left_type: Type; > > right_type: Type; > > left_min: Target.Int; > > left_max: Target.Int; > > right_min: Target.Int; > > right_max: Target.Int; > > left_signed: BOOLEAN; > > right_signed: BOOLEAN; > > BEGIN > > > > always_true := FALSE; > > always_false := FALSE; > > > > WITH left = stack [SCheck (2, "Compare-left")], > > right = stack [SCheck (1, "Compare-right")] DO > > > > left_type := left.type; > > right_type := right.type; > > > > IF left.min_valid > > AND left.max_valid > > AND right.min_valid > > AND right.max_valid > > AND Target.OrdinalType[left_type] > > AND Target.OrdinalType[right_type] THEN > > > > left_min := left.min; > > left_max := left.max; > > right_min := right.min; > > right_max := right.max; > > left_signed := Target.SignedType[left_type]; > > right_signed := Target.SignedType[right_type]; > > > > (* First handle types that match in signedness. *) > > > > IF left_signed = right_signed THEN > > > > (* Check for ranges with no overlap. *) > > > > IF left_signed (* and right_signed *) THEN > > IF TInt.LT(left_max, right_min) THEN > > always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; > > always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; > > ELSIF TInt.GT(left_min, right_max) THEN > > always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; > > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; > > END; > > ELSE (* left_signed and right_signed both false *) > > IF TWord.LT(left_max, right_min) THEN > > always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; > > always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; > > ELSIF TWord.GT(left_min, right_max) THEN > > always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; > > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; > > END; > > END; > > > > (* Check for overlap just on the edge, e.g. [0..1] compared to [1..2]. *) > > > > IF NOT (always_true OR always_false) THEN > > IF TInt.EQ(left_max, right_min) THEN > > always_true := op = Cmp.LE; > > always_false := op = Cmp.GT; > > ELSIF TInt.EQ(left_min, right_max) THEN > > always_true := op = Cmp.GE; > > always_false := op = Cmp.LT; > > END; > > END; > > > > (* Handle equal subranges with one element, not likely to occur. *) > > > > IF NOT (always_true OR always_false) THEN > > IF TInt.EQ(left_max, left_min) > > AND TInt.EQ(left_max, right_max) > > AND TInt.EQ(left_max, right_min) THEN > > always_true := op IN SET OF Cmp{Cmp.GE, Cmp.LE, Cmp.EQ}; > > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.GT, Cmp.NE}; > > END; > > END; > > ELSE > > > > (* Now deal with mixed up types (signed compared to unsigned). > > * We may be able to merge these by setting some min/max > > * to zero. That is, the minimum of an unsigned type is zero. > > * However we want to be sure not to interpret unsigned min/max > > * as signed. > > *) > > > > IF left_signed THEN > > IF TInt.LT(left_max, TInt.Zero) THEN > > always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; > > always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; > > ELSIF TInt.EQ(left_max, TInt.Zero) THEN > > always_true := op = Cmp.LE; > > always_false := op = Cmp.GT; > > END; > > ELSE (* right is signed *) > > IF TInt.LT(right_max, TInt.Zero) THEN > > always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; > > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; > > ELSIF TInt.EQ(right_max, TInt.Zero) THEN > > always_true := op = Cmp.GE; > > always_false := op = Cmp.LT; > > END; > > END; > > END; > > END; > > > > <* ASSERT NOT (always_true AND always_false) *> > > > > IF always_true OR always_false THEN > > Discard(right_type); > > Discard(left_type); > > IF always_true THEN > > cg.load_integer (Target.Integer.cg_type, TInt.One); > > ELSE > > cg.load_integer (Target.Integer.cg_type, TInt.Zero); > > END > > ELSE > > IF Force_pair (commute := TRUE) THEN > > op := M3CG.SwappedCompare [op]; > > END; > > cg.compare (t, Target.Integer.cg_type, op); > > SPop (2, "Compare"); > > END; > 1836,1837d2008 > < cg.compare (t, Target.Integer.cg_type, op); > < SPop (2, "Compare"); > 2880a3052,3055 > > x.min := TInt.Zero; > > x.max := TInt.Zero; > > x.min_valid := FALSE; > > x.max_valid := FALSE; > 2977c3152,3153 > < BEGIN > --- > > BEGIN > > debug := debug OR RTParams.IsPresent ("m3front_cg_debug"); > Index: m3-sys/m3front/src/values/Variable.m3 > =================================================================== > RCS file: /usr/cvs/cm3/m3-sys/m3front/src/values/Variable.m3,v > retrieving revision 1.13 > diff -r1.13 Variable.m3 > 362a363,365 > > VAR min: Target.Int; > > max: Target.Int; > > bounds_valid: BOOLEAN; > 395c398,401 > < CG.Load (t.cg_var, t.offset, t.size, t.cg_align, t.stk_type); > --- > > (*GetBounds (t, min, max); > > bounds_valid := TInt.LE(min, max);*) > > bounds_valid := t.tipe # NIL AND Type.GetBounds(t.tipe, min, max) AND TInt.LE(min, max); > > CG.Load (t.cg_var, t.offset, t.size, t.cg_align, t.stk_type, bounds_valid, bounds_valid, min, max); > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Mon May 23 01:18:02 2011 From: jay.krell at cornell.edu (Jay K) Date: Sun, 22 May 2011 23:18:02 +0000 Subject: [M3devel] range analysis? In-Reply-To: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> References: , <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> Message-ID: Well, I can build the whole tree and see how many times it helps. I think this is a pretty standard optimization technique. Though it'd work better with compiler-derived additional information. I initially happened upon this idea developing test cases. > The code assumes the minimum of a type is less than or equal to its maximum. I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. - Jay Subject: Re: range analysis? From: hosking at cs.purdue.edu Date: Sun, 22 May 2011 14:51:59 -0400 CC: m3devel at elegosoft.com To: jay.krell at cornell.edu So, one question is: what benefit does this really give? Your examples seem a little contrived. On May 22, 2011, at 4:26 AM, Jay K wrote:I've been sitting on this diff a long while. In some places the frontend knows the bounds of a type/value and will optimize away range checks. I'm pretty sure. This makes it do that more. I haven't looked at or tested this in ages. But the basic idea seems sound, simple, easy enough to get a few small wins from. For example if you have: a: [-10..-1]; b: [1..10]; then all comparisons between a and b are compile-time constant. Comparisons of cardinals to negative numbers, likewise. One thing maybe missing below is handling of empty ranges like a: [1..-1]; The code assumes the minimum of a type is less than or equal to its maximum. Index: m3-sys/m3front/src/misc/CG.i3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.i3,v retrieving revision 1.15 diff -r1.15 CG.i3 11c11 < IMPORT Target, M3CG, M3; --- > IMPORT Target, M3CG, M3, TInt; 402c402,406 < PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type); --- > PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type; > min_valid: BOOLEAN := FALSE; > max_valid: BOOLEAN := FALSE; > min: Target.Int := TInt.Zero; > max: Target.Int := TInt.Zero); 414,415c418,423 < PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0); < (* == Load (v, o, t.size, t.align, t) *) --- > PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0; > min_valid: BOOLEAN := FALSE; > max_valid: BOOLEAN := FALSE; > min: Target.Int := TInt.Zero; > max: Target.Int := TInt.Zero); > (* == Load (v, o, t.size, t.align, t, min/max...) *) Index: m3-sys/m3front/src/misc/CG.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.m3,v retrieving revision 1.40 diff -r1.40 CG.m3 13c13 < IMPORT M3, M3CG, M3CG_Ops, M3CG_Check; --- > IMPORT M3, M3CG, M3CG_Ops, M3CG_Check, RTIO, RTParams; 45a46,49 > min_valid : BOOLEAN := FALSE; (* whether or not min is valid *) > max_valid : BOOLEAN := FALSE; (* whether or not max is valid *) > min : Target.Int := TInt.Zero; (* the minimum possible value *) > max : Target.Int := TInt.Zero; (* the maximum possible value *) 80c84,85 < VAR --- > VAR > debug := FALSE; 604a610,614 > v.min := TInt.Zero; > v.max := TInt.Zero; > v.min_valid := FALSE; > v.max_valid := FALSE; > 766a777,780 > x.min := TInt.Zero; > x.max := TInt.Zero; > x.min_valid := FALSE; > x.max_valid := FALSE; 978a993,995 > IF debug THEN > RTIO.PutText("m3front:cg:Init_int:NOT in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); > END; 980a998,1001 > END; > > IF debug THEN > RTIO.PutText("m3front:cg:Init_int:in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); 1266c1287,1291 < PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type) = --- > PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type; > min_valid: BOOLEAN := FALSE; > max_valid: BOOLEAN := FALSE; > min: Target.Int := TInt.Zero; > max: Target.Int := TInt.Zero) = 1276c1301 < SimpleLoad (v, o, t); --- > SimpleLoad (v, o, t, min_valid, max_valid, min, max); 1291c1316 < SimpleLoad (v, o, best_type); --- > SimpleLoad (v, o, best_type, min_valid, max_valid, min, max); 1312c1337,1341 < PROCEDURE SimpleLoad (v: Var; o: Offset; t: Type) = --- > PROCEDURE SimpleLoad (v: Var; o: Offset; t: Type; > min_valid: BOOLEAN := FALSE; > max_valid: BOOLEAN := FALSE; > min: Target.Int := TInt.Zero; > max: Target.Int := TInt.Zero) = 1323a1353,1356 > x.min_valid := min_valid; > x.max_valid := max_valid; > x.min := min; > x.max := max; 1339a1373,1376 > x.min := TInt.Zero; > x.max := TInt.Zero; > x.min_valid := FALSE; > x.max_valid := FALSE; 1347a1385,1388 > stack[tos-1].min := TInt.Zero; > stack[tos-1].max := TInt.Zero; > stack[tos-1].min_valid := FALSE; > stack[tos-1].max_valid := FALSE; 1350c1391,1395 < PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0) = --- > PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0; > min_valid: BOOLEAN := FALSE; > max_valid: BOOLEAN := FALSE; > min: Target.Int := TInt.Zero; > max: Target.Int := TInt.Zero) = 1352c1397 < SimpleLoad (v, o, t); --- > SimpleLoad (v, o, t, min_valid, max_valid, min, max); 1815a1861,1864 > x.min_valid := TRUE; > x.max_valid := TRUE; > x.min := i; > x.max := i; 1832,1834c1881,2007 < BEGIN < IF Force_pair (commute := TRUE) THEN < op := M3CG.SwappedCompare [op]; --- > VAR always_true: BOOLEAN; > always_false: BOOLEAN; > left_type: Type; > right_type: Type; > left_min: Target.Int; > left_max: Target.Int; > right_min: Target.Int; > right_max: Target.Int; > left_signed: BOOLEAN; > right_signed: BOOLEAN; > BEGIN > > always_true := FALSE; > always_false := FALSE; > > WITH left = stack [SCheck (2, "Compare-left")], > right = stack [SCheck (1, "Compare-right")] DO > > left_type := left.type; > right_type := right.type; > > IF left.min_valid > AND left.max_valid > AND right.min_valid > AND right.max_valid > AND Target.OrdinalType[left_type] > AND Target.OrdinalType[right_type] THEN > > left_min := left.min; > left_max := left.max; > right_min := right.min; > right_max := right.max; > left_signed := Target.SignedType[left_type]; > right_signed := Target.SignedType[right_type]; > > (* First handle types that match in signedness. *) > > IF left_signed = right_signed THEN > > (* Check for ranges with no overlap. *) > > IF left_signed (* and right_signed *) THEN > IF TInt.LT(left_max, right_min) THEN > always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; > ELSIF TInt.GT(left_min, right_max) THEN > always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; > END; > ELSE (* left_signed and right_signed both false *) > IF TWord.LT(left_max, right_min) THEN > always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; > ELSIF TWord.GT(left_min, right_max) THEN > always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; > END; > END; > > (* Check for overlap just on the edge, e.g. [0..1] compared to [1..2]. *) > > IF NOT (always_true OR always_false) THEN > IF TInt.EQ(left_max, right_min) THEN > always_true := op = Cmp.LE; > always_false := op = Cmp.GT; > ELSIF TInt.EQ(left_min, right_max) THEN > always_true := op = Cmp.GE; > always_false := op = Cmp.LT; > END; > END; > > (* Handle equal subranges with one element, not likely to occur. *) > > IF NOT (always_true OR always_false) THEN > IF TInt.EQ(left_max, left_min) > AND TInt.EQ(left_max, right_max) > AND TInt.EQ(left_max, right_min) THEN > always_true := op IN SET OF Cmp{Cmp.GE, Cmp.LE, Cmp.EQ}; > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.GT, Cmp.NE}; > END; > END; > ELSE > > (* Now deal with mixed up types (signed compared to unsigned). > * We may be able to merge these by setting some min/max > * to zero. That is, the minimum of an unsigned type is zero. > * However we want to be sure not to interpret unsigned min/max > * as signed. > *) > > IF left_signed THEN > IF TInt.LT(left_max, TInt.Zero) THEN > always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; > ELSIF TInt.EQ(left_max, TInt.Zero) THEN > always_true := op = Cmp.LE; > always_false := op = Cmp.GT; > END; > ELSE (* right is signed *) > IF TInt.LT(right_max, TInt.Zero) THEN > always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; > ELSIF TInt.EQ(right_max, TInt.Zero) THEN > always_true := op = Cmp.GE; > always_false := op = Cmp.LT; > END; > END; > END; > END; > > <* ASSERT NOT (always_true AND always_false) *> > > IF always_true OR always_false THEN > Discard(right_type); > Discard(left_type); > IF always_true THEN > cg.load_integer (Target.Integer.cg_type, TInt.One); > ELSE > cg.load_integer (Target.Integer.cg_type, TInt.Zero); > END > ELSE > IF Force_pair (commute := TRUE) THEN > op := M3CG.SwappedCompare [op]; > END; > cg.compare (t, Target.Integer.cg_type, op); > SPop (2, "Compare"); > END; 1836,1837d2008 < cg.compare (t, Target.Integer.cg_type, op); < SPop (2, "Compare"); 2880a3052,3055 > x.min := TInt.Zero; > x.max := TInt.Zero; > x.min_valid := FALSE; > x.max_valid := FALSE; 2977c3152,3153 < BEGIN --- > BEGIN > debug := debug OR RTParams.IsPresent ("m3front_cg_debug"); Index: m3-sys/m3front/src/values/Variable.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/values/Variable.m3,v retrieving revision 1.13 diff -r1.13 Variable.m3 362a363,365 > VAR min: Target.Int; > max: Target.Int; > bounds_valid: BOOLEAN; 395c398,401 < CG.Load (t.cg_var, t.offset, t.size, t.cg_align, t.stk_type); --- > (*GetBounds (t, min, max); > bounds_valid := TInt.LE(min, max);*) > bounds_valid := t.tipe # NIL AND Type.GetBounds(t.tipe, min, max) AND TInt.LE(min, max); > CG.Load (t.cg_var, t.offset, t.size, t.cg_align, t.stk_type, bounds_valid, bounds_valid, min, max); -------------- next part -------------- An HTML attachment was scrubbed... URL: From hendrik at topoi.pooq.com Mon May 23 14:41:53 2011 From: hendrik at topoi.pooq.com (Hendrik Boom) Date: Mon, 23 May 2011 08:41:53 -0400 Subject: [M3devel] range analysis? In-Reply-To: References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> Message-ID: <20110523124153.GA31229@topoi.pooq.com> On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: > > Well, I can build the whole tree and see how many times it helps. > I think this is a pretty standard optimization technique. > Though it'd work better with compiler-derived additional information. > > I initially happened upon this idea developing test cases. > > > The code assumes the minimum of a type is less than or equal to its maximum. > > I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. What *is* the semantics of a range whose minimum is greater than its maximum? There plainly can't be any values in this range. How is a variable of this tyoe initialized? Not to some arbitrary value of the type, because there aren't any. I can see this type being useful to admit convenient generalizations -- for example, an array with n elements can still exist if n happens to be zero, but it seems to me that any code involving a value of the range for subscripts for this array must be simple unexecutable. Or is there some latitude available in the principle that a value of a variable must always be of the correct type? -- hendrik From hosking at cs.purdue.edu Mon May 23 16:31:24 2011 From: hosking at cs.purdue.edu (Tony Hosking) Date: Mon, 23 May 2011 10:31:24 -0400 Subject: [M3devel] range analysis? In-Reply-To: <20110523124153.GA31229@topoi.pooq.com> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> Message-ID: <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> An empty subrange gives a warning in the compiler. But, the semantics is that it is empty, and has no values of the type. You cannot allocate (NEW) an empty type. You cannot declare a field of empty type. Nor can you declare a variable of empty type. On May 23, 2011, at 8:41 AM, Hendrik Boom wrote: > On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: >> >> Well, I can build the whole tree and see how many times it helps. >> I think this is a pretty standard optimization technique. >> Though it'd work better with compiler-derived additional information. >> >> I initially happened upon this idea developing test cases. >> >>> The code assumes the minimum of a type is less than or equal to its maximum. >> >> I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. > > What *is* the semantics of a range whose minimum is greater than its > maximum? There plainly can't be any values in this range. How is a > variable of this tyoe initialized? Not to some arbitrary value of the > type, because there aren't any. I can see this type being useful to > admit convenient generalizations -- for example, an array with n > elements can still exist if n happens to be zero, but it seems to me > that any code involving a value of the range for subscripts for this > array must be simple unexecutable. > > Or is there some latitude available in the principle that a value of a > variable must always be of the correct type? > > -- hendrik From rodney_bates at lcwb.coop Mon May 23 18:45:14 2011 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Mon, 23 May 2011 11:45:14 -0500 Subject: [M3devel] range analysis? In-Reply-To: <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> Message-ID: <4DDA8F1A.3070207@lcwb.coop> On 05/23/2011 09:31 AM, Tony Hosking wrote: > An empty subrange gives a warning in the compiler. By my experiments, empty subrange, empty enumeration, and arrays thereof don't warn. > But, the semantics is that it is empty, and has no values of the type. > You cannot allocate (NEW) an empty type. > You cannot declare a field of empty type. It seems odd that we have this rule for fields, but no corresponding prohibition against arrays with empty element types. By experiments, cm3 allows this, for both fixed and open arrays, but treats such array types as empty types, something the language also does not say. At the least, the language and the compiler should agree with each other. Maybe records/objects and arrays should be treated consistently here? > Nor can you declare a variable of empty type. Again, oddly, there is no such prohibition in the language against declaring a formal parameter of empty type. Cm3 prohibits it, and calls it a 'variable' in the error message. Again, language and compiler should agree. The language also prohibits applying FIRST and LAST to the empty enumeration, but they are OK applied to an empty subrange. This makes sense, because they return values of the base type of the argument type, and such values exist for an empty subrange but not the empty enumeration, whose base type is only itself. > > On May 23, 2011, at 8:41 AM, Hendrik Boom wrote: > >> On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: >>> >>> Well, I can build the whole tree and see how many times it helps. >>> I think this is a pretty standard optimization technique. >>> Though it'd work better with compiler-derived additional information. >>> >>> I initially happened upon this idea developing test cases. >>> >>>> The code assumes the minimum of a type is less than or equal to its maximum. >>> >>> I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. >> >> What *is* the semantics of a range whose minimum is greater than its >> maximum? There plainly can't be any values in this range. How is a >> variable of this tyoe initialized? Not to some arbitrary value of the >> type, because there aren't any. I can see this type being useful to >> admit convenient generalizations -- for example, an array with n >> elements can still exist if n happens to be zero, but it seems to me >> that any code involving a value of the range for subscripts for this >> array must be simple unexecutable. >> >> Or is there some latitude available in the principle that a value of a >> variable must always be of the correct type? >> >> -- hendrik > > From hosking at cs.purdue.edu Mon May 23 18:54:36 2011 From: hosking at cs.purdue.edu (Tony Hosking) Date: Mon, 23 May 2011 12:54:36 -0400 Subject: [M3devel] range analysis? In-Reply-To: <4DDA8F1A.3070207@lcwb.coop> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> <4DDA8F1A.3070207@lcwb.coop> Message-ID: <8C9E1E77-686F-42E0-87FA-B573A4A02CC9@cs.purdue.edu> On May 23, 2011, at 12:45 PM, Rodney M. Bates wrote: > On 05/23/2011 09:31 AM, Tony Hosking wrote: >> An empty subrange gives a warning in the compiler. > > By my experiments, empty subrange, empty enumeration, and arrays > thereof don't warn. Sorry yes, you're right. But usage to declare any variable does. > >> But, the semantics is that it is empty, and has no values of the type. >> You cannot allocate (NEW) an empty type. >> You cannot declare a field of empty type. > > It seems odd that we have this rule for fields, but no corresponding > prohibition against arrays with empty element types. By experiments, > cm3 allows this, for both fixed and open arrays, but treats such array > types as empty types, something the language also does not say. > > At the least, the language and the compiler should agree with each other. > Maybe records/objects and arrays should be treated consistently here? Yes, I suppose so. >> Nor can you declare a variable of empty type. > > Again, oddly, there is no such prohibition in the language against > declaring a formal parameter of empty type. Cm3 prohibits it, > and calls it a 'variable' in the error message. You're right, though it's not the parameter that errors but the variable associated with the parameter. > Again, language and compiler should agree. Can you point me to the relevant entries in the language spec? > > The language also prohibits applying FIRST and LAST to the empty > enumeration, but they are OK applied to an empty subrange. > This makes sense, because they return values of the base type > of the argument type, and such values exist for an empty subrange > but not the empty enumeration, whose base type is only itself. > >> >> On May 23, 2011, at 8:41 AM, Hendrik Boom wrote: >> >>> On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: >>>> >>>> Well, I can build the whole tree and see how many times it helps. >>>> I think this is a pretty standard optimization technique. >>>> Though it'd work better with compiler-derived additional information. >>>> >>>> I initially happened upon this idea developing test cases. >>>> >>>>> The code assumes the minimum of a type is less than or equal to its maximum. >>>> >>>> I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. >>> >>> What *is* the semantics of a range whose minimum is greater than its >>> maximum? There plainly can't be any values in this range. How is a >>> variable of this tyoe initialized? Not to some arbitrary value of the >>> type, because there aren't any. I can see this type being useful to >>> admit convenient generalizations -- for example, an array with n >>> elements can still exist if n happens to be zero, but it seems to me >>> that any code involving a value of the range for subscripts for this >>> array must be simple unexecutable. >>> >>> Or is there some latitude available in the principle that a value of a >>> variable must always be of the correct type? >>> >>> -- hendrik >> >> From rodney_bates at lcwb.coop Mon May 23 20:26:52 2011 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Mon, 23 May 2011 13:26:52 -0500 Subject: [M3devel] range analysis? In-Reply-To: <8C9E1E77-686F-42E0-87FA-B573A4A02CC9@cs.purdue.edu> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> <4DDA8F1A.3070207@lcwb.coop> <8C9E1E77-686F-42E0-87FA-B573A4A02CC9@cs.purdue.edu> Message-ID: <4DDAA6EC.8060401@lcwb.coop> This needs more thought. On the one hand, 2.2.3 on array types allows the explicit element type in either kind of array type definition to be empty, unlike the way 2.2.4 on record types requires a field type to be nonempty. On the other hand, 2.2 has a general prohibition against declaring a variable of empty type, and it is all over the language spec that the elements of arrays are "variables". The general definition of variable in 2.1 would apply to array elements. Thre are numerous places that describe things that can be done with a variable that we all informally know can be done to an element, as it should be and we all have done many times. Moreover, 2.2.3 says in the first paragraph that the elements are variables. So here, the compiler is too liberal, and the language would be clearer with an explicit rule against empty element types. I haven't spotted anywhere a parameter is specifically called a variable, and it is not required to have a nonempty type in the description of parameter declarations. However, it certainly seems to me to fit the definition of variable, and as above, there are lots of things we know can be done with it that the language simply describes as doable to a variable. Moreover, for every mode, there is a rule that at call time, the formal is "bound to" a variable, which pretty well makes it variable in any context where it can be used. Even in a keyword binding, we are getting ready to bind it to a variable very soon. So maybe we need to 1) say a formal parameter is a variable, and 2) say the type in a parameter declaration must be nonempty. The language definition is also full of an ambiguity in its use of "variable" that I have been bothered by in talking about programming languages in general for years. One meaning is the meaning I have been talking about, The other is the kind of variable that is declared by a VAR declaration (not a VAR parameter). There are some uses in the language that I think need to have this latter meaning in order to be right. So we need a different or qualified term for this narrower meaning. On 05/23/2011 11:54 AM, Tony Hosking wrote: > > On May 23, 2011, at 12:45 PM, Rodney M. Bates wrote: > >> On 05/23/2011 09:31 AM, Tony Hosking wrote: >>> An empty subrange gives a warning in the compiler. >> >> By my experiments, empty subrange, empty enumeration, and arrays >> thereof don't warn. > > Sorry yes, you're right. But usage to declare any variable does. > >> >>> But, the semantics is that it is empty, and has no values of the type. >>> You cannot allocate (NEW) an empty type. >>> You cannot declare a field of empty type. >> >> It seems odd that we have this rule for fields, but no corresponding >> prohibition against arrays with empty element types. By experiments, >> cm3 allows this, for both fixed and open arrays, but treats such array >> types as empty types, something the language also does not say. >> >> At the least, the language and the compiler should agree with each other. >> Maybe records/objects and arrays should be treated consistently here? > > Yes, I suppose so. > >>> Nor can you declare a variable of empty type. >> >> Again, oddly, there is no such prohibition in the language against >> declaring a formal parameter of empty type. Cm3 prohibits it, >> and calls it a 'variable' in the error message. > > You're right, though it's not the parameter that errors but the variable associated with the parameter. > >> Again, language and compiler should agree. > > Can you point me to the relevant entries in the language spec? > >> >> The language also prohibits applying FIRST and LAST to the empty >> enumeration, but they are OK applied to an empty subrange. >> This makes sense, because they return values of the base type >> of the argument type, and such values exist for an empty subrange >> but not the empty enumeration, whose base type is only itself. >> >>> >>> On May 23, 2011, at 8:41 AM, Hendrik Boom wrote: >>> >>>> On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: >>>>> >>>>> Well, I can build the whole tree and see how many times it helps. >>>>> I think this is a pretty standard optimization technique. >>>>> Though it'd work better with compiler-derived additional information. >>>>> >>>>> I initially happened upon this idea developing test cases. >>>>> >>>>>> The code assumes the minimum of a type is less than or equal to its maximum. >>>>> >>>>> I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. >>>> >>>> What *is* the semantics of a range whose minimum is greater than its >>>> maximum? There plainly can't be any values in this range. How is a >>>> variable of this tyoe initialized? Not to some arbitrary value of the >>>> type, because there aren't any. I can see this type being useful to >>>> admit convenient generalizations -- for example, an array with n >>>> elements can still exist if n happens to be zero, but it seems to me >>>> that any code involving a value of the range for subscripts for this >>>> array must be simple unexecutable. >>>> >>>> Or is there some latitude available in the principle that a value of a >>>> variable must always be of the correct type? >>>> >>>> -- hendrik >>> >>> > > From hosking at cs.purdue.edu Mon May 23 20:45:37 2011 From: hosking at cs.purdue.edu (Tony Hosking) Date: Mon, 23 May 2011 14:45:37 -0400 Subject: [M3devel] range analysis? In-Reply-To: <4DDAA6EC.8060401@lcwb.coop> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> <4DDA8F1A.3070207@lcwb.coop> <8C9E1E77-686F-42E0-87FA-B573A4A02CC9@cs.purdue.edu> <4DDAA6EC.8060401@lcwb.coop> Message-ID: <45B5D160-9E80-4BB9-8411-F3976BCDC207@cs.purdue.edu> On May 23, 2011, at 2:26 PM, Rodney M. Bates wrote: > This needs more thought. On the one hand, 2.2.3 on array types allows > the explicit element type in either kind of array type definition to > be empty, unlike the way 2.2.4 on record types requires a field type > to be nonempty. I note that an array type of empty elements is itself empty and cannot be instantiated. > On the other hand, 2.2 has a general prohibition against declaring a > variable of empty type, and it is all over the language spec that the > elements of arrays are "variables". The general definition of variable > in 2.1 would apply to array elements. Thre are numerous places that > describe things that can be done with a variable that we all informally > know can be done to an element, as it should be and we all have done > many times. Moreover, 2.2.3 says in the first paragraph that the > elements are variables. So, it seems to me that we could simply disallow empty array elements and be within spec. > So here, the compiler is too liberal, and the language would be clearer > with an explicit rule against empty element types. Right. > I haven't spotted anywhere a parameter is specifically called a variable, > and it is not required to have a nonempty type in the description of > parameter declarations. However, it certainly seems to me to fit > the definition of variable, and as above, there are lots of things > we know can be done with it that the language simply describes as > doable to a variable. Moreover, for every mode, there is a rule > that at call time, the formal is "bound to" a variable, which pretty > well makes it variable in any context where it can be used. Even in > a keyword binding, we are getting ready to bind it to a variable > very soon. Right. > So maybe we need to 1) say a formal parameter is a variable, and A formal parameter is not in itself a variable. It's part of a type (the signature) not an implementation of that type. But every formal parameter has a corresponding variable in the body of the procedure that implements a given signature. > 2) say the type in a parameter declaration must be nonempty. This seems overwrought. I would stop simply at the variables (not the types) and let the binding of formal parameters to variables take care of the check as it currently does. > The language definition is also full of an ambiguity in its use > of "variable" that I have been bothered by in talking about programming > languages in general for years. One meaning is the meaning I have been > talking about, The other is the kind of variable that is declared by a > VAR declaration (not a VAR parameter). There are some uses in the > language that I think need to have this latter meaning in order to be right. Can you enumerate? > So we need a different or qualified term for this narrower meaning. > > On 05/23/2011 11:54 AM, Tony Hosking wrote: >> >> On May 23, 2011, at 12:45 PM, Rodney M. Bates wrote: >> >>> On 05/23/2011 09:31 AM, Tony Hosking wrote: >>>> An empty subrange gives a warning in the compiler. >>> >>> By my experiments, empty subrange, empty enumeration, and arrays >>> thereof don't warn. >> >> Sorry yes, you're right. But usage to declare any variable does. >> >>> >>>> But, the semantics is that it is empty, and has no values of the type. >>>> You cannot allocate (NEW) an empty type. >>>> You cannot declare a field of empty type. >>> >>> It seems odd that we have this rule for fields, but no corresponding >>> prohibition against arrays with empty element types. By experiments, >>> cm3 allows this, for both fixed and open arrays, but treats such array >>> types as empty types, something the language also does not say. >>> >>> At the least, the language and the compiler should agree with each other. >>> Maybe records/objects and arrays should be treated consistently here? >> >> Yes, I suppose so. >> >>>> Nor can you declare a variable of empty type. >>> >>> Again, oddly, there is no such prohibition in the language against >>> declaring a formal parameter of empty type. Cm3 prohibits it, >>> and calls it a 'variable' in the error message. >> >> You're right, though it's not the parameter that errors but the variable associated with the parameter. >> >>> Again, language and compiler should agree. >> >> Can you point me to the relevant entries in the language spec? >> >>> >>> The language also prohibits applying FIRST and LAST to the empty >>> enumeration, but they are OK applied to an empty subrange. >>> This makes sense, because they return values of the base type >>> of the argument type, and such values exist for an empty subrange >>> but not the empty enumeration, whose base type is only itself. >>> >>>> >>>> On May 23, 2011, at 8:41 AM, Hendrik Boom wrote: >>>> >>>>> On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: >>>>>> >>>>>> Well, I can build the whole tree and see how many times it helps. >>>>>> I think this is a pretty standard optimization technique. >>>>>> Though it'd work better with compiler-derived additional information. >>>>>> >>>>>> I initially happened upon this idea developing test cases. >>>>>> >>>>>>> The code assumes the minimum of a type is less than or equal to its maximum. >>>>>> >>>>>> I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. >>>>> >>>>> What *is* the semantics of a range whose minimum is greater than its >>>>> maximum? There plainly can't be any values in this range. How is a >>>>> variable of this tyoe initialized? Not to some arbitrary value of the >>>>> type, because there aren't any. I can see this type being useful to >>>>> admit convenient generalizations -- for example, an array with n >>>>> elements can still exist if n happens to be zero, but it seems to me >>>>> that any code involving a value of the range for subscripts for this >>>>> array must be simple unexecutable. >>>>> >>>>> Or is there some latitude available in the principle that a value of a >>>>> variable must always be of the correct type? >>>>> >>>>> -- hendrik >>>> >>>> >> >> From dabenavidesd at yahoo.es Mon May 23 22:44:11 2011 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Mon, 23 May 2011 21:44:11 +0100 (BST) Subject: [M3devel] range analysis? In-Reply-To: Message-ID: <346693.80219.qm@web29707.mail.ird.yahoo.com> Hi all: in one process it might be good to check for those optimization, but then you might want to abstract them all to allow to be pessimistic or to analyze them in ESC. This should require some good knowledge of the compiler though, which is maybe a harder task than just build a VCG but perhaps is too slow for m3cg, maybe for native backends, is more justifiable if so. Perhaps there is enough good trade off to do so. Thanks in advance --- El dom, 22/5/11, Jay K escribi?: De: Jay K Asunto: Re: [M3devel] range analysis? Para: "Tony" CC: "m3devel" Fecha: domingo, 22 de mayo, 2011 18:18 Well, I can build the whole tree and see how many times it helps. I think this is a pretty standard optimization technique. Though it'd work better with compiler-derived additional information. I initially happened upon this idea developing test cases. ?> The code assumes the minimum of a type is less than or equal to its maximum. I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. ?- Jay Subject: Re: range analysis? From: hosking at cs.purdue.edu Date: Sun, 22 May 2011 14:51:59 -0400 CC: m3devel at elegosoft.com To: jay.krell at cornell.edu So, one question is: what benefit does this really give? ?Your examples seem a little contrived. On May 22, 2011, at 4:26 AM, Jay K wrote: I've been sitting on this diff a long while. In some places the frontend knows the bounds of a type/value and will optimize away range checks. I'm pretty sure. This makes it do that more. I haven't looked at or tested this in ages. But the basic idea seems sound, simple, easy enough to get a few small wins from. For example if you have: a: [-10..-1]; b: [1..10]; then all comparisons between a and b are compile-time constant. Comparisons of cardinals to negative numbers, likewise. One thing maybe missing below is handling of empty ranges like a: [1..-1]; The code assumes the minimum of a type is less than or equal to its maximum. Index: m3-sys/m3front/src/misc/CG.i3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.i3,v retrieving revision 1.15 diff -r1.15 CG.i3 11c11 < IMPORT Target, M3CG, M3; --- > IMPORT Target, M3CG, M3, TInt; 402c402,406 < PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type); --- > PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type; >???????????????? min_valid: BOOLEAN := FALSE; >???????????????? max_valid: BOOLEAN := FALSE; >???????????????? min: Target.Int := TInt.Zero; >???????????????? max: Target.Int := TInt.Zero); 414,415c418,423 < PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0); < (* == Load (v, o, t.size, t.align, t) *) --- > PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0; >???????????????????? min_valid: BOOLEAN := FALSE; >???????????????????? max_valid: BOOLEAN := FALSE; >???????????????????? min: Target.Int := TInt.Zero; >???????????????????? max: Target.Int := TInt.Zero); > (* == Load (v, o, t.size, t.align, t, min/max...) *) Index: m3-sys/m3front/src/misc/CG.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.m3,v retrieving revision 1.40 diff -r1.40 CG.m3 13c13 < IMPORT M3, M3CG, M3CG_Ops, M3CG_Check; --- > IMPORT M3, M3CG, M3CG_Ops, M3CG_Check, RTIO, RTParams; 45a46,49 >???? min_valid : BOOLEAN := FALSE; (* whether or not min is valid *) >???? max_valid : BOOLEAN := FALSE; (* whether or not max is valid *) >???? min?????? : Target.Int := TInt.Zero; (* the minimum possible value *) >???? max?????? : Target.Int := TInt.Zero; (* the maximum possible value *) 80c84,85 < VAR --- > VAR >?? debug := FALSE; 604a610,614 >???? v.min?????? := TInt.Zero; >???? v.max?????? := TInt.Zero; >???? v.min_valid := FALSE; >???? v.max_valid := FALSE; >? 766a777,780 >???? x.min?????? := TInt.Zero; >???? x.max?????? := TInt.Zero; >???? x.min_valid := FALSE; >???? x.max_valid := FALSE; 978a993,995 >?????? IF debug THEN >???????? RTIO.PutText("m3front:cg:Init_int:NOT in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); >?????? END; 980a998,1001 >???? END; >? >???? IF debug THEN >?????? RTIO.PutText("m3front:cg:Init_int:in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); 1266c1287,1291 < PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type) = --- > PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type; >???????????????? min_valid: BOOLEAN := FALSE; >???????????????? max_valid: BOOLEAN := FALSE; >???????????????? min: Target.Int := TInt.Zero; >???????????????? max: Target.Int := TInt.Zero) = 1276c1301 ?????? SimpleLoad (v, o, t, min_valid, max_valid, min, max); 1291c1316 ???????? SimpleLoad (v, o, best_type, min_valid, max_valid, min, max); 1312c1337,1341 < PROCEDURE SimpleLoad (v: Var;? o: Offset;? t: Type) = --- > PROCEDURE SimpleLoad (v: Var;? o: Offset;? t: Type; >?????????????????????? min_valid: BOOLEAN := FALSE; >?????????????????????? max_valid: BOOLEAN := FALSE; >?????????????????????? min: Target.Int := TInt.Zero; >?????????????????????? max: Target.Int := TInt.Zero) = 1323a1353,1356 >?????? x.min_valid := min_valid; >?????? x.max_valid := max_valid; >?????? x.min?????? := min; >?????? x.max?????? := max; 1339a1373,1376 >?????? x.min?????? := TInt.Zero; >?????? x.max?????? := TInt.Zero; >?????? x.min_valid := FALSE; >?????? x.max_valid := FALSE; 1347a1385,1388 >???? stack[tos-1].min?????? := TInt.Zero; >???? stack[tos-1].max?????? := TInt.Zero; >???? stack[tos-1].min_valid := FALSE; >???? stack[tos-1].max_valid := FALSE; 1350c1391,1395 < PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0) = --- > PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0; >???????????????????? min_valid: BOOLEAN := FALSE; >???????????????????? max_valid: BOOLEAN := FALSE; >???????????????????? min: Target.Int := TInt.Zero; >???????????????????? max: Target.Int := TInt.Zero) = 1352c1397 ???? SimpleLoad (v, o, t, min_valid, max_valid, min, max); 1815a1861,1864 >?????? x.min_valid := TRUE; >?????? x.max_valid := TRUE; >?????? x.min := i; >?????? x.max := i; 1832,1834c1881,2007 ?? VAR always_true: BOOLEAN; >?????? always_false: BOOLEAN; >?????? left_type: Type; >?????? right_type: Type; >?????? left_min: Target.Int; >?????? left_max: Target.Int; >?????? right_min: Target.Int; >?????? right_max: Target.Int; >?????? left_signed: BOOLEAN; >?????? right_signed: BOOLEAN; >?? BEGIN >? >???? always_true := FALSE; >???? always_false := FALSE; >? >???? WITH left? = stack [SCheck (2, "Compare-left")], >????????? right = stack [SCheck (1, "Compare-right")] DO >? >?????? left_type := left.type; >?????? right_type := right.type; >? >?????? IF????? left.min_valid >?????????? AND left.max_valid >?????????? AND right.min_valid >?????????? AND right.max_valid >?????????? AND Target.OrdinalType[left_type] >?????????? AND Target.OrdinalType[right_type] THEN >? >???????? left_min := left.min; >???????? left_max := left.max; >???????? right_min := right.min; >???????? right_max := right.max; >???????? left_signed := Target.SignedType[left_type]; >???????? right_signed := Target.SignedType[right_type]; >? >???????? (* First handle types that match in signedness. *) >? >???????? IF left_signed = right_signed THEN >? >?????????? (* Check for ranges with no overlap. *) >? >?????????? IF left_signed (* and right_signed *) THEN >???????????? IF TInt.LT(left_max, right_min) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; >???????????? ELSIF TInt.GT(left_min, right_max) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; >???????????? END; >?????????? ELSE (* left_signed and right_signed both false *) >???????????? IF TWord.LT(left_max, right_min) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; >???????????? ELSIF TWord.GT(left_min, right_max) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; >???????????? END; >?????????? END; >? >?????????? (* Check for overlap just on the edge, e.g. [0..1] compared to [1..2]. *) >? >?????????? IF NOT (always_true OR always_false) THEN >???????????? IF TInt.EQ(left_max, right_min) THEN >?????????????? always_true := op = Cmp.LE; >?????????????? always_false := op = Cmp.GT; >???????????? ELSIF TInt.EQ(left_min, right_max) THEN >?????????????? always_true := op = Cmp.GE; >?????????????? always_false := op = Cmp.LT; >???????????? END; >?????????? END; >? >?????????? (* Handle equal subranges with one element, not likely to occur. *) >? >?????????? IF NOT (always_true OR always_false) THEN >???????????? IF????? TInt.EQ(left_max, left_min) >???????????????? AND TInt.EQ(left_max, right_max) >???????????????? AND TInt.EQ(left_max, right_min) THEN >?????????????? always_true? := op IN SET OF Cmp{Cmp.GE, Cmp.LE, Cmp.EQ}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.GT, Cmp.NE}; >???????????? END; >?????????? END; >???????? ELSE >? >?????????? (* Now deal with mixed up types (signed compared to unsigned). >??????????? * We may be able to merge these by setting some min/max >??????????? * to zero. That is, the minimum of an unsigned type is zero. >??????????? * However we want to be sure not to interpret unsigned min/max >??????????? * as signed. >??????????? *) >? >?????????? IF left_signed THEN >???????????? IF TInt.LT(left_max, TInt.Zero) THEN >?????????????? always_true? := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; >???????????? ELSIF TInt.EQ(left_max, TInt.Zero) THEN >?????????????? always_true? := op = Cmp.LE; >?????????????? always_false := op = Cmp.GT; >???????????? END; >?????????? ELSE (* right is signed *) >???????????? IF TInt.LT(right_max, TInt.Zero) THEN >?????????????? always_true? := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; >???????????? ELSIF TInt.EQ(right_max, TInt.Zero) THEN >?????????????? always_true := op = Cmp.GE; >?????????????? always_false := op = Cmp.LT; >???????????? END; >?????????? END; >???????? END; >?????? END; >?? >?????? <* ASSERT NOT (always_true AND always_false) *> >? >?????? IF always_true OR always_false THEN >???????? Discard(right_type); >???????? Discard(left_type); >???????? IF always_true THEN >?????????? cg.load_integer (Target.Integer.cg_type, TInt.One); >???????? ELSE >?????????? cg.load_integer (Target.Integer.cg_type, TInt.Zero); >???????? END >?????? ELSE >???????? IF Force_pair (commute := TRUE) THEN >?????????? op := M3CG.SwappedCompare [op]; >???????? END; >???????? cg.compare (t, Target.Integer.cg_type, op); >???????? SPop (2, "Compare"); >?????? END; 1836,1837d2008 ?????? x.min?????? := TInt.Zero; >?????? x.max?????? := TInt.Zero; >?????? x.min_valid := FALSE; >?????? x.max_valid := FALSE; 2977c3152,3153 < BEGIN --- > BEGIN >?? debug := debug OR RTParams.IsPresent ("m3front_cg_debug"); Index: m3-sys/m3front/src/values/Variable.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/values/Variable.m3,v retrieving revision 1.13 diff -r1.13 Variable.m3 362a363,365 >?? VAR min: Target.Int; >?????? max: Target.Int; >?????? bounds_valid: BOOLEAN; 395c398,401 ???????? (*GetBounds (t, min, max); >???????? bounds_valid := TInt.LE(min, max);*) >???????? bounds_valid := t.tipe # NIL AND Type.GetBounds(t.tipe, min, max) AND TInt.LE(min, max); >???????? CG.Load (t.cg_var, t.offset, t.size, t.cg_align, t.stk_type, bounds_valid, bounds_valid, min, max); -------------- next part -------------- An HTML attachment was scrubbed... URL: From hendrik at topoi.pooq.com Tue May 24 00:53:02 2011 From: hendrik at topoi.pooq.com (Hendrik Boom) Date: Mon, 23 May 2011 18:53:02 -0400 Subject: [M3devel] range analysis? In-Reply-To: <4DDAA6EC.8060401@lcwb.coop> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> <4DDA8F1A.3070207@lcwb.coop> <8C9E1E77-686F-42E0-87FA-B573A4A02CC9@cs.purdue.edu> <4DDAA6EC.8060401@lcwb.coop> Message-ID: <20110523225302.GA8980@topoi.pooq.com> On Mon, May 23, 2011 at 01:26:52PM -0500, Rodney M. Bates wrote: > This needs more thought. On the one hand, 2.2.3 on array types allows > the explicit element type in either kind of array type definition to > be empty, Well, the array might be empty, in which case no nonexistent values would be required when the array is created. > unlike the way 2.2.4 on record types requires a field type > to be nonempty. > > On the other hand, 2.2 has a general prohibition against declaring a > variable of empty type, and it is all over the language spec that the > elements of arrays are "variables". The general definition of variable > in 2.1 would apply to array elements. Thre are numerous places that > describe things that can be done with a variable that we all informally > know can be done to an element, as it should be and we all have done > many times. Moreover, 2.2.3 says in the first paragraph that the > elements are variables. > > So here, the compiler is too liberal, and the language would be clearer > with an explicit rule against empty element types. > > I haven't spotted anywhere a parameter is specifically called a variable, > and it is not required to have a nonempty type in the description of > parameter declarations. However, it certainly seems to me to fit > the definition of variable, and as above, there are lots of things > we know can be done with it that the language simply describes as > doable to a variable. Moreover, for every mode, there is a rule > that at call time, the formal is "bound to" a variable, which pretty > well makes it variable in any context where it can be used. Even in > a keyword binding, we are getting ready to bind it to a variable > very soon. > > So maybe we need to 1) say a formal parameter is a variable, and > 2) say the type in a parameter declaration must be nonempty. > > The language definition is also full of an ambiguity in its use > of "variable" that I have been bothered by in talking about programming > languages in general for years. One meaning is the meaning I have been > talking about, The other is the kind of variable that is declared by a > VAR declaration (not a VAR parameter). There are some uses in the > language that I think need to have this latter meaning in order to be right. > > So we need a different or qualified term for this narrower meaning. > > On 05/23/2011 11:54 AM, Tony Hosking wrote: >> >> On May 23, 2011, at 12:45 PM, Rodney M. Bates wrote: >> >>> On 05/23/2011 09:31 AM, Tony Hosking wrote: >>>> An empty subrange gives a warning in the compiler. >>> >>> By my experiments, empty subrange, empty enumeration, and arrays >>> thereof don't warn. >> >> Sorry yes, you're right. But usage to declare any variable does. >> >>> >>>> But, the semantics is that it is empty, and has no values of the type. >>>> You cannot allocate (NEW) an empty type. >>>> You cannot declare a field of empty type. >>> >>> It seems odd that we have this rule for fields, but no corresponding >>> prohibition against arrays with empty element types. By experiments, >>> cm3 allows this, for both fixed and open arrays, but treats such array >>> types as empty types, something the language also does not say. >>> >>> At the least, the language and the compiler should agree with each other. >>> Maybe records/objects and arrays should be treated consistently here? >> >> Yes, I suppose so. >> >>>> Nor can you declare a variable of empty type. >>> >>> Again, oddly, there is no such prohibition in the language against >>> declaring a formal parameter of empty type. Cm3 prohibits it, >>> and calls it a 'variable' in the error message. >> >> You're right, though it's not the parameter that errors but the variable associated with the parameter. >> >>> Again, language and compiler should agree. >> >> Can you point me to the relevant entries in the language spec? >> >>> >>> The language also prohibits applying FIRST and LAST to the empty >>> enumeration, but they are OK applied to an empty subrange. >>> This makes sense, because they return values of the base type >>> of the argument type, and such values exist for an empty subrange >>> but not the empty enumeration, whose base type is only itself. >>> >>>> >>>> On May 23, 2011, at 8:41 AM, Hendrik Boom wrote: >>>> >>>>> On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: >>>>>> >>>>>> Well, I can build the whole tree and see how many times it helps. >>>>>> I think this is a pretty standard optimization technique. >>>>>> Though it'd work better with compiler-derived additional information. >>>>>> >>>>>> I initially happened upon this idea developing test cases. >>>>>> >>>>>>> The code assumes the minimum of a type is less than or equal to its maximum. >>>>>> >>>>>> I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. >>>>> >>>>> What *is* the semantics of a range whose minimum is greater than its >>>>> maximum? There plainly can't be any values in this range. How is a >>>>> variable of this tyoe initialized? Not to some arbitrary value of the >>>>> type, because there aren't any. I can see this type being useful to >>>>> admit convenient generalizations -- for example, an array with n >>>>> elements can still exist if n happens to be zero, but it seems to me >>>>> that any code involving a value of the range for subscripts for this >>>>> array must be simple unexecutable. >>>>> >>>>> Or is there some latitude available in the principle that a value of a >>>>> variable must always be of the correct type? >>>>> >>>>> -- hendrik >>>> >>>> >> >> From hendrik at topoi.pooq.com Tue May 24 00:55:08 2011 From: hendrik at topoi.pooq.com (Hendrik Boom) Date: Mon, 23 May 2011 18:55:08 -0400 Subject: [M3devel] range analysis? In-Reply-To: <45B5D160-9E80-4BB9-8411-F3976BCDC207@cs.purdue.edu> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> <4DDA8F1A.3070207@lcwb.coop> <8C9E1E77-686F-42E0-87FA-B573A4A02CC9@cs.purdue.edu> <4DDAA6EC.8060401@lcwb.coop> <45B5D160-9E80-4BB9-8411-F3976BCDC207@cs.purdue.edu> Message-ID: <20110523225508.GB8980@topoi.pooq.com> On Mon, May 23, 2011 at 02:45:37PM -0400, Tony Hosking wrote: > > On May 23, 2011, at 2:26 PM, Rodney M. Bates wrote: > > > This needs more thought. On the one hand, 2.2.3 on array types allows > > the explicit element type in either kind of array type definition to > > be empty, unlike the way 2.2.4 on record types requires a field type > > to be nonempty. > > I note that an array type of empty elements is itself empty and cannot be instantiated. > > > On the other hand, 2.2 has a general prohibition against declaring a > > variable of empty type, and it is all over the language spec that the > > elements of arrays are "variables". The general definition of variable > > in 2.1 would apply to array elements. Thre are numerous places that > > describe things that can be done with a variable that we all informally > > know can be done to an element, as it should be and we all have done > > many times. Moreover, 2.2.3 says in the first paragraph that the > > elements are variables. > > So, it seems to me that we could simply disallow empty array elements and be within spec. You mean the array elements are empty? or that the element type is empty? These are very different concepts. From dabenavidesd at yahoo.es Tue May 24 00:54:33 2011 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Mon, 23 May 2011 23:54:33 +0100 (BST) Subject: [M3devel] range analysis? In-Reply-To: <346693.80219.qm@web29707.mail.ird.yahoo.com> Message-ID: <781156.80626.qm@web29716.mail.ird.yahoo.com> Hi all: an this could be even more payable in embedded architectures, of course there is always more work, but the market, is moving towards that I mean, people are *really* worried about lock-free data structures, etc, when there are tools that tackle that automatically or treat them formally and in Modula-3, see: http://www.eetimes.com/discussion/break-points/4027598/Executing-software-contracts I'm thinking in this more seriously, and by the amount of time they devised modula-3 end (1996 if I may say so), which is at least 10 years ahead of its common use and the tools they did as was their goal in DEC SRC, we are still on the front or struggling if so (and off-time of 5 years still have some room to speak up). And could be more if you think in separate efforts on it. As I heard from an old M3 friend, Obliq was? merely about to be the language standard for web and yet not one of them has the full technology of it as is (meaning it was the first agent language and it has type inference, and it's fast!). think in the Java JS binomial, for example and alike. I mean such an example, of usage and precedence in time is enough to say the quality in terms of the all package (Modula-3 and scripting language) Ok, it would be interesting to see why did they to take such decision (old friend's wish). Thanks in advance --- El lun, 23/5/11, Daniel Alejandro Benavides D. escribi?: De: Daniel Alejandro Benavides D. Asunto: Re: [M3devel] range analysis? Para: "Tony" , "Jay K" CC: "m3devel" Fecha: lunes, 23 de mayo, 2011 15:44 Hi all: in one process it might be good to check for those optimization, but then you might want to abstract them all to allow to be pessimistic or to analyze them in ESC. This should require some good knowledge of the compiler though, which is maybe a harder task than just build a VCG but perhaps is too slow for m3cg, maybe for native backends, is more justifiable if so. Perhaps there is enough good trade off to do so. Thanks in advance --- El dom, 22/5/11, Jay K escribi?: De: Jay K Asunto: Re: [M3devel] range analysis? Para: "Tony" CC: "m3devel" Fecha: domingo, 22 de mayo, 2011 18:18 Well, I can build the whole tree and see how many times it helps. I think this is a pretty standard optimization technique. Though it'd work better with compiler-derived additional information. I initially happened upon this idea developing test cases. ?> The code assumes the minimum of a type is less than or equal to its maximum. I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. ?- Jay Subject: Re: range analysis? From: hosking at cs.purdue.edu Date: Sun, 22 May 2011 14:51:59 -0400 CC: m3devel at elegosoft.com To: jay.krell at cornell.edu So, one question is: what benefit does this really give? ?Your examples seem a little contrived. On May 22, 2011, at 4:26 AM, Jay K wrote: I've been sitting on this diff a long while. In some places the frontend knows the bounds of a type/value and will optimize away range checks. I'm pretty sure. This makes it do that more. I haven't looked at or tested this in ages. But the basic idea seems sound, simple, easy enough to get a few small wins from. For example if you have: a: [-10..-1]; b: [1..10]; then all comparisons between a and b are compile-time constant. Comparisons of cardinals to negative numbers, likewise. One thing maybe missing below is handling of empty ranges like a: [1..-1]; The code assumes the minimum of a type is less than or equal to its maximum. Index: m3-sys/m3front/src/misc/CG.i3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.i3,v retrieving revision 1.15 diff -r1.15 CG.i3 11c11 < IMPORT Target, M3CG, M3; --- > IMPORT Target, M3CG, M3, TInt; 402c402,406 < PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type); --- > PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type; >???????????????? min_valid: BOOLEAN := FALSE; >???????????????? max_valid: BOOLEAN := FALSE; >???????????????? min: Target.Int := TInt.Zero; >???????????????? max: Target.Int := TInt.Zero); 414,415c418,423 < PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0); < (* == Load (v, o, t.size, t.align, t) *) --- > PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0; >???????????????????? min_valid: BOOLEAN := FALSE; >???????????????????? max_valid: BOOLEAN := FALSE; >???????????????????? min: Target.Int := TInt.Zero; >???????????????????? max: Target.Int := TInt.Zero); > (* == Load (v, o, t.size, t.align, t, min/max...) *) Index: m3-sys/m3front/src/misc/CG.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.m3,v retrieving revision 1.40 diff -r1.40 CG.m3 13c13 < IMPORT M3, M3CG, M3CG_Ops, M3CG_Check; --- > IMPORT M3, M3CG, M3CG_Ops, M3CG_Check, RTIO, RTParams; 45a46,49 >???? min_valid : BOOLEAN := FALSE; (* whether or not min is valid *) >???? max_valid : BOOLEAN := FALSE; (* whether or not max is valid *) >???? min?????? : Target.Int := TInt.Zero; (* the minimum possible value *) >???? max?????? : Target.Int := TInt.Zero; (* the maximum possible value *) 80c84,85 < VAR --- > VAR >?? debug := FALSE; 604a610,614 >???? v.min?????? := TInt.Zero; >???? v.max?????? := TInt.Zero; >???? v.min_valid := FALSE; >???? v.max_valid := FALSE; >? 766a777,780 >???? x.min?????? := TInt.Zero; >???? x.max?????? := TInt.Zero; >???? x.min_valid := FALSE; >???? x.max_valid := FALSE; 978a993,995 >?????? IF debug THEN >???????? RTIO.PutText("m3front:cg:Init_int:NOT in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); >?????? END; 980a998,1001 >???? END; >? >???? IF debug THEN >?????? RTIO.PutText("m3front:cg:Init_int:in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); 1266c1287,1291 < PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type) = --- > PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type; >???????????????? min_valid: BOOLEAN := FALSE; >???????????????? max_valid: BOOLEAN := FALSE; >???????????????? min: Target.Int := TInt.Zero; >???????????????? max: Target.Int := TInt.Zero) = 1276c1301 ?????? SimpleLoad (v, o, t, min_valid, max_valid, min, max); 1291c1316 ???????? SimpleLoad (v, o, best_type, min_valid, max_valid, min, max); 1312c1337,1341 < PROCEDURE SimpleLoad (v: Var;? o: Offset;? t: Type) = --- > PROCEDURE SimpleLoad (v: Var;? o: Offset;? t: Type; >?????????????????????? min_valid: BOOLEAN := FALSE; >?????????????????????? max_valid: BOOLEAN := FALSE; >?????????????????????? min: Target.Int := TInt.Zero; >?????????????????????? max: Target.Int := TInt.Zero) = 1323a1353,1356 >?????? x.min_valid := min_valid; >?????? x.max_valid := max_valid; >?????? x.min?????? := min; >?????? x.max?????? := max; 1339a1373,1376 >?????? x.min?????? := TInt.Zero; >?????? x.max?????? := TInt.Zero; >?????? x.min_valid := FALSE; >?????? x.max_valid := FALSE; 1347a1385,1388 >???? stack[tos-1].min?????? := TInt.Zero; >???? stack[tos-1].max?????? := TInt.Zero; >???? stack[tos-1].min_valid := FALSE; >???? stack[tos-1].max_valid := FALSE; 1350c1391,1395 < PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0) = --- > PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0; >???????????????????? min_valid: BOOLEAN := FALSE; >???????????????????? max_valid: BOOLEAN := FALSE; >???????????????????? min: Target.Int := TInt.Zero; >???????????????????? max: Target.Int := TInt.Zero) = 1352c1397 ???? SimpleLoad (v, o, t, min_valid, max_valid, min, max); 1815a1861,1864 >?????? x.min_valid := TRUE; >?????? x.max_valid := TRUE; >?????? x.min := i; >?????? x.max := i; 1832,1834c1881,2007 ?? VAR always_true: BOOLEAN; >?????? always_false: BOOLEAN; >?????? left_type: Type; >?????? right_type: Type; >?????? left_min: Target.Int; >?????? left_max: Target.Int; >?????? right_min: Target.Int; >?????? right_max: Target.Int; >?????? left_signed: BOOLEAN; >?????? right_signed: BOOLEAN; >?? BEGIN >? >???? always_true := FALSE; >???? always_false := FALSE; >? >???? WITH left? = stack [SCheck (2, "Compare-left")], >????????? right = stack [SCheck (1, "Compare-right")] DO >? >?????? left_type := left.type; >?????? right_type := right.type; >? >?????? IF????? left.min_valid >?????????? AND left.max_valid >?????????? AND right.min_valid >?????????? AND right.max_valid >?????????? AND Target.OrdinalType[left_type] >?????????? AND Target.OrdinalType[right_type] THEN >? >???????? left_min := left.min; >???????? left_max := left.max; >???????? right_min := right.min; >???????? right_max := right.max; >???????? left_signed := Target.SignedType[left_type]; >???????? right_signed := Target.SignedType[right_type]; >? >???????? (* First handle types that match in signedness. *) >? >???????? IF left_signed = right_signed THEN >? >?????????? (* Check for ranges with no overlap. *) >? >?????????? IF left_signed (* and right_signed *) THEN >???????????? IF TInt.LT(left_max, right_min) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; >???????????? ELSIF TInt.GT(left_min, right_max) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; >???????????? END; >?????????? ELSE (* left_signed and right_signed both false *) >???????????? IF TWord.LT(left_max, right_min) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; >???????????? ELSIF TWord.GT(left_min, right_max) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; >???????????? END; >?????????? END; >? >?????????? (* Check for overlap just on the edge, e.g. [0..1] compared to [1..2]. *) >? >?????????? IF NOT (always_true OR always_false) THEN >???????????? IF TInt.EQ(left_max, right_min) THEN >?????????????? always_true := op = Cmp.LE; >?????????????? always_false := op = Cmp.GT; >???????????? ELSIF TInt.EQ(left_min, right_max) THEN >?????????????? always_true := op = Cmp.GE; >?????????????? always_false := op = Cmp.LT; >???????????? END; >?????????? END; >? >?????????? (* Handle equal subranges with one element, not likely to occur. *) >? >?????????? IF NOT (always_true OR always_false) THEN >???????????? IF????? TInt.EQ(left_max, left_min) >???????????????? AND TInt.EQ(left_max, right_max) >???????????????? AND TInt.EQ(left_max, right_min) THEN >?????????????? always_true? := op IN SET OF Cmp{Cmp.GE, Cmp.LE, Cmp.EQ}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.GT, Cmp.NE}; >???????????? END; >?????????? END; >???????? ELSE >? >?????????? (* Now deal with mixed up types (signed compared to unsigned). >??????????? * We may be able to merge these by setting some min/max >??????????? * to zero. That is, the minimum of an unsigned type is zero. >??????????? * However we want to be sure not to interpret unsigned min/max >??????????? * as signed. >??????????? *) >? >?????????? IF left_signed THEN >???????????? IF TInt.LT(left_max, TInt.Zero) THEN >?????????????? always_true? := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; >???????????? ELSIF TInt.EQ(left_max, TInt.Zero) THEN >?????????????? always_true? := op = Cmp.LE; >?????????????? always_false := op = Cmp.GT; >???????????? END; >?????????? ELSE (* right is signed *) >???????????? IF TInt.LT(right_max, TInt.Zero) THEN >?????????????? always_true? := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; >???????????? ELSIF TInt.EQ(right_max, TInt.Zero) THEN >?????????????? always_true := op = Cmp.GE; >?????????????? always_false := op = Cmp.LT; >???????????? END; >?????????? END; >???????? END; >?????? END; >?? >?????? <* ASSERT NOT (always_true AND always_false) *> >? >?????? IF always_true OR always_false THEN >???????? Discard(right_type); >???????? Discard(left_type); >???????? IF always_true THEN >?????????? cg.load_integer (Target.Integer.cg_type, TInt.One); >???????? ELSE >?????????? cg.load_integer (Target.Integer.cg_type, TInt.Zero); >???????? END >?????? ELSE >???????? IF Force_pair (commute := TRUE) THEN >?????????? op := M3CG.SwappedCompare [op]; >???????? END; >???????? cg.compare (t, Target.Integer.cg_type, op); >???????? SPop (2, "Compare"); >?????? END; 1836,1837d2008 ?????? x.min?????? := TInt.Zero; >?????? x.max?????? := TInt.Zero; >?????? x.min_valid := FALSE; >?????? x.max_valid := FALSE; 2977c3152,3153 < BEGIN --- > BEGIN >?? debug := debug OR RTParams.IsPresent ("m3front_cg_debug"); Index: m3-sys/m3front/src/values/Variable.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/values/Variable.m3,v retrieving revision 1.13 diff -r1.13 Variable.m3 362a363,365 >?? VAR min: Target.Int; >?????? max: Target.Int; >?????? bounds_valid: BOOLEAN; 395c398,401 ???????? (*GetBounds (t, min, max); >???????? bounds_valid := TInt.LE(min, max);*) >???????? bounds_valid := t.tipe # NIL AND Type.GetBounds(t.tipe, min, max) AND TInt.LE(min, max); >???????? CG.Load (t.cg_var, t.offset, t.size, t.cg_align, t.stk_type, bounds_valid, bounds_valid, min, max); -------------- next part -------------- An HTML attachment was scrubbed... URL: From dabenavidesd at yahoo.es Tue May 24 01:22:51 2011 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Tue, 24 May 2011 00:22:51 +0100 (BST) Subject: [M3devel] range analysis? In-Reply-To: <781156.80626.qm@web29716.mail.ird.yahoo.com> Message-ID: <970550.60419.qm@web29711.mail.ird.yahoo.com> Hi all: and even more I can tell you there is plenty of teaching material on Object Oriented software construction in Modula-3 for Meyer's book,? then what about pulishing it and rewriting it in scripts of Obliq, which is harder to learn from 0, I guess Modula-3, but even if we facilitate that, what else is missing here (mentor, zeus3D, Obliq3D examples). See the same mentioned linked page. About Second comment on that page, I guess they talk about Model driven checking, from which there are tools that do that and are open source if they are so much we could adapt them to it. See Spec language. Thanks in advance --- El lun, 23/5/11, Daniel Alejandro Benavides D. escribi?: De: Daniel Alejandro Benavides D. Asunto: Re: [M3devel] range analysis? Para: "Tony" , "Jay K" CC: "m3devel" Fecha: lunes, 23 de mayo, 2011 17:54 Hi all: an this could be even more payable in embedded architectures, of course there is always more work, but the market, is moving towards that I mean, people are *really* worried about lock-free data structures, etc, when there are tools that tackle that automatically or treat them formally and in Modula-3, see: http://www.eetimes.com/discussion/break-points/4027598/Executing-software-contracts I'm thinking in this more seriously, and by the amount of time they devised modula-3 end (1996 if I may say so), which is at least 10 years ahead of its common use and the tools they did as was their goal in DEC SRC, we are still on the front or struggling if so (and off-time of 5 years still have some room to speak up). And could be more if you think in separate efforts on it. As I heard from an old M3 friend, Obliq was? merely about to be the language standard for web and yet not one of them has the full technology of it as is (meaning it was the first agent language and it has type inference, and it's fast!). think in the Java JS binomial, for example and alike. I mean such an example, of usage and precedence in time is enough to say the quality in terms of the all package (Modula-3 and scripting language) Ok, it would be interesting to see why did they to take such decision (old friend's wish). Thanks in advance --- El lun, 23/5/11, Daniel Alejandro Benavides D. escribi?: De: Daniel Alejandro Benavides D. Asunto: Re: [M3devel] range analysis? Para: "Tony" , "Jay K" CC: "m3devel" Fecha: lunes, 23 de mayo, 2011 15:44 Hi all: in one process it might be good to check for those optimization, but then you might want to abstract them all to allow to be pessimistic or to analyze them in ESC. This should require some good knowledge of the compiler though, which is maybe a harder task than just build a VCG but perhaps is too slow for m3cg, maybe for native backends, is more justifiable if so. Perhaps there is enough good trade off to do so. Thanks in advance --- El dom, 22/5/11, Jay K escribi?: De: Jay K Asunto: Re: [M3devel] range analysis? Para: "Tony" CC: "m3devel" Fecha: domingo, 22 de mayo, 2011 18:18 Well, I can build the whole tree and see how many times it helps. I think this is a pretty standard optimization technique. Though it'd work better with compiler-derived additional information. I initially happened upon this idea developing test cases. ?> The code assumes the minimum of a type is less than or equal to its maximum. I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. ?- Jay Subject: Re: range analysis? From: hosking at cs.purdue.edu Date: Sun, 22 May 2011 14:51:59 -0400 CC: m3devel at elegosoft.com To: jay.krell at cornell.edu So, one question is: what benefit does this really give? ?Your examples seem a little contrived. On May 22, 2011, at 4:26 AM, Jay K wrote: I've been sitting on this diff a long while. In some places the frontend knows the bounds of a type/value and will optimize away range checks. I'm pretty sure. This makes it do that more. I haven't looked at or tested this in ages. But the basic idea seems sound, simple, easy enough to get a few small wins from. For example if you have: a: [-10..-1]; b: [1..10]; then all comparisons between a and b are compile-time constant. Comparisons of cardinals to negative numbers, likewise. One thing maybe missing below is handling of empty ranges like a: [1..-1]; The code assumes the minimum of a type is less than or equal to its maximum. Index: m3-sys/m3front/src/misc/CG.i3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.i3,v retrieving revision 1.15 diff -r1.15 CG.i3 11c11 < IMPORT Target, M3CG, M3; --- > IMPORT Target, M3CG, M3, TInt; 402c402,406 < PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type); --- > PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type; >???????????????? min_valid: BOOLEAN := FALSE; >???????????????? max_valid: BOOLEAN := FALSE; >???????????????? min: Target.Int := TInt.Zero; >???????????????? max: Target.Int := TInt.Zero); 414,415c418,423 < PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0); < (* == Load (v, o, t.size, t.align, t) *) --- > PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0; >???????????????????? min_valid: BOOLEAN := FALSE; >???????????????????? max_valid: BOOLEAN := FALSE; >???????????????????? min: Target.Int := TInt.Zero; >???????????????????? max: Target.Int := TInt.Zero); > (* == Load (v, o, t.size, t.align, t, min/max...) *) Index: m3-sys/m3front/src/misc/CG.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.m3,v retrieving revision 1.40 diff -r1.40 CG.m3 13c13 < IMPORT M3, M3CG, M3CG_Ops, M3CG_Check; --- > IMPORT M3, M3CG, M3CG_Ops, M3CG_Check, RTIO, RTParams; 45a46,49 >???? min_valid : BOOLEAN := FALSE; (* whether or not min is valid *) >???? max_valid : BOOLEAN := FALSE; (* whether or not max is valid *) >???? min?????? : Target.Int := TInt.Zero; (* the minimum possible value *) >???? max?????? : Target.Int := TInt.Zero; (* the maximum possible value *) 80c84,85 < VAR --- > VAR >?? debug := FALSE; 604a610,614 >???? v.min?????? := TInt.Zero; >???? v.max?????? := TInt.Zero; >???? v.min_valid := FALSE; >???? v.max_valid := FALSE; >? 766a777,780 >???? x.min?????? := TInt.Zero; >???? x.max?????? := TInt.Zero; >???? x.min_valid := FALSE; >???? x.max_valid := FALSE; 978a993,995 >?????? IF debug THEN >???????? RTIO.PutText("m3front:cg:Init_int:NOT in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); >?????? END; 980a998,1001 >???? END; >? >???? IF debug THEN >?????? RTIO.PutText("m3front:cg:Init_int:in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); 1266c1287,1291 < PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type) = --- > PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type; >???????????????? min_valid: BOOLEAN := FALSE; >???????????????? max_valid: BOOLEAN := FALSE; >???????????????? min: Target.Int := TInt.Zero; >???????????????? max: Target.Int := TInt.Zero) = 1276c1301 ?????? SimpleLoad (v, o, t, min_valid, max_valid, min, max); 1291c1316 ???????? SimpleLoad (v, o, best_type, min_valid, max_valid, min, max); 1312c1337,1341 < PROCEDURE SimpleLoad (v: Var;? o: Offset;? t: Type) = --- > PROCEDURE SimpleLoad (v: Var;? o: Offset;? t: Type; >?????????????????????? min_valid: BOOLEAN := FALSE; >?????????????????????? max_valid: BOOLEAN := FALSE; >?????????????????????? min: Target.Int := TInt.Zero; >?????????????????????? max: Target.Int := TInt.Zero) = 1323a1353,1356 >?????? x.min_valid := min_valid; >?????? x.max_valid := max_valid; >?????? x.min?????? := min; >?????? x.max?????? := max; 1339a1373,1376 >?????? x.min?????? := TInt.Zero; >?????? x.max?????? := TInt.Zero; >?????? x.min_valid := FALSE; >?????? x.max_valid := FALSE; 1347a1385,1388 >???? stack[tos-1].min?????? := TInt.Zero; >???? stack[tos-1].max?????? := TInt.Zero; >???? stack[tos-1].min_valid := FALSE; >???? stack[tos-1].max_valid := FALSE; 1350c1391,1395 < PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0) = --- > PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0; >???????????????????? min_valid: BOOLEAN := FALSE; >???????????????????? max_valid: BOOLEAN := FALSE; >???????????????????? min: Target.Int := TInt.Zero; >???????????????????? max: Target.Int := TInt.Zero) = 1352c1397 ???? SimpleLoad (v, o, t, min_valid, max_valid, min, max); 1815a1861,1864 >?????? x.min_valid := TRUE; >?????? x.max_valid := TRUE; >?????? x.min := i; >?????? x.max := i; 1832,1834c1881,2007 ?? VAR always_true: BOOLEAN; >?????? always_false: BOOLEAN; >?????? left_type: Type; >?????? right_type: Type; >?????? left_min: Target.Int; >?????? left_max: Target.Int; >?????? right_min: Target.Int; >?????? right_max: Target.Int; >?????? left_signed: BOOLEAN; >?????? right_signed: BOOLEAN; >?? BEGIN >? >???? always_true := FALSE; >???? always_false := FALSE; >? >???? WITH left? = stack [SCheck (2, "Compare-left")], >????????? right = stack [SCheck (1, "Compare-right")] DO >? >?????? left_type := left.type; >?????? right_type := right.type; >? >?????? IF????? left.min_valid >?????????? AND left.max_valid >?????????? AND right.min_valid >?????????? AND right.max_valid >?????????? AND Target.OrdinalType[left_type] >?????????? AND Target.OrdinalType[right_type] THEN >? >???????? left_min := left.min; >???????? left_max := left.max; >???????? right_min := right.min; >???????? right_max := right.max; >???????? left_signed := Target.SignedType[left_type]; >???????? right_signed := Target.SignedType[right_type]; >? >???????? (* First handle types that match in signedness. *) >? >???????? IF left_signed = right_signed THEN >? >?????????? (* Check for ranges with no overlap. *) >? >?????????? IF left_signed (* and right_signed *) THEN >???????????? IF TInt.LT(left_max, right_min) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; >???????????? ELSIF TInt.GT(left_min, right_max) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; >???????????? END; >?????????? ELSE (* left_signed and right_signed both false *) >???????????? IF TWord.LT(left_max, right_min) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; >???????????? ELSIF TWord.GT(left_min, right_max) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; >???????????? END; >?????????? END; >? >?????????? (* Check for overlap just on the edge, e.g. [0..1] compared to [1..2]. *) >? >?????????? IF NOT (always_true OR always_false) THEN >???????????? IF TInt.EQ(left_max, right_min) THEN >?????????????? always_true := op = Cmp.LE; >?????????????? always_false := op = Cmp.GT; >???????????? ELSIF TInt.EQ(left_min, right_max) THEN >?????????????? always_true := op = Cmp.GE; >?????????????? always_false := op = Cmp.LT; >???????????? END; >?????????? END; >? >?????????? (* Handle equal subranges with one element, not likely to occur. *) >? >?????????? IF NOT (always_true OR always_false) THEN >???????????? IF????? TInt.EQ(left_max, left_min) >???????????????? AND TInt.EQ(left_max, right_max) >???????????????? AND TInt.EQ(left_max, right_min) THEN >?????????????? always_true? := op IN SET OF Cmp{Cmp.GE, Cmp.LE, Cmp.EQ}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.GT, Cmp.NE}; >???????????? END; >?????????? END; >???????? ELSE >? >?????????? (* Now deal with mixed up types (signed compared to unsigned). >??????????? * We may be able to merge these by setting some min/max >??????????? * to zero. That is, the minimum of an unsigned type is zero. >??????????? * However we want to be sure not to interpret unsigned min/max >??????????? * as signed. >??????????? *) >? >?????????? IF left_signed THEN >???????????? IF TInt.LT(left_max, TInt.Zero) THEN >?????????????? always_true? := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; >???????????? ELSIF TInt.EQ(left_max, TInt.Zero) THEN >?????????????? always_true? := op = Cmp.LE; >?????????????? always_false := op = Cmp.GT; >???????????? END; >?????????? ELSE (* right is signed *) >???????????? IF TInt.LT(right_max, TInt.Zero) THEN >?????????????? always_true? := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; >???????????? ELSIF TInt.EQ(right_max, TInt.Zero) THEN >?????????????? always_true := op = Cmp.GE; >?????????????? always_false := op = Cmp.LT; >???????????? END; >?????????? END; >???????? END; >?????? END; >?? >?????? <* ASSERT NOT (always_true AND always_false) *> >? >?????? IF always_true OR always_false THEN >???????? Discard(right_type); >???????? Discard(left_type); >???????? IF always_true THEN >?????????? cg.load_integer (Target.Integer.cg_type, TInt.One); >???????? ELSE >?????????? cg.load_integer (Target.Integer.cg_type, TInt.Zero); >???????? END >?????? ELSE >???????? IF Force_pair (commute := TRUE) THEN >?????????? op := M3CG.SwappedCompare [op]; >???????? END; >???????? cg.compare (t, Target.Integer.cg_type, op); >???????? SPop (2, "Compare"); >?????? END; 1836,1837d2008 ?????? x.min?????? := TInt.Zero; >?????? x.max?????? := TInt.Zero; >?????? x.min_valid := FALSE; >?????? x.max_valid := FALSE; 2977c3152,3153 < BEGIN --- > BEGIN >?? debug := debug OR RTParams.IsPresent ("m3front_cg_debug"); Index: m3-sys/m3front/src/values/Variable.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/values/Variable.m3,v retrieving revision 1.13 diff -r1.13 Variable.m3 362a363,365 >?? VAR min: Target.Int; >?????? max: Target.Int; >?????? bounds_valid: BOOLEAN; 395c398,401 ???????? (*GetBounds (t, min, max); >???????? bounds_valid := TInt.LE(min, max);*) >???????? bounds_valid := t.tipe # NIL AND Type.GetBounds(t.tipe, min, max) AND TInt.LE(min, max); >???????? CG.Load (t.cg_var, t.offset, t.size, t.cg_align, t.stk_type, bounds_valid, bounds_valid, min, max); -------------- next part -------------- An HTML attachment was scrubbed... URL: From rodney_bates at lcwb.coop Tue May 24 02:16:18 2011 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Mon, 23 May 2011 19:16:18 -0500 Subject: [M3devel] range analysis? In-Reply-To: <20110523225302.GA8980@topoi.pooq.com> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> <4DDA8F1A.3070207@lcwb.coop> <8C9E1E77-686F-42E0-87FA-B573A4A02CC9@cs.purdue.edu> <4DDAA6EC.8060401@lcwb.coop> <20110523225302.GA8980@topoi.pooq.com> Message-ID: <4DDAF8D2.2090800@lcwb.coop> On 05/23/2011 05:53 PM, Hendrik Boom wrote: > On Mon, May 23, 2011 at 01:26:52PM -0500, Rodney M. Bates wrote: >> This needs more thought. On the one hand, 2.2.3 on array types allows >> the explicit element type in either kind of array type definition to >> be empty, > > Well, the array might be empty, in which case no nonexistent values > would be required when the array is created. Good point. Right now, the compiler does not allow creation of such arrays, either fixed or open. The error messages both refer to the _array type_ whose elements also have empty type as an "empty type", regardless of whether the element count is zero or positive. > >> unlike the way 2.2.4 on record types requires a field type >> to be nonempty. >> >> On the other hand, 2.2 has a general prohibition against declaring a >> variable of empty type, and it is all over the language spec that the >> elements of arrays are "variables". The general definition of variable >> in 2.1 would apply to array elements. Thre are numerous places that >> describe things that can be done with a variable that we all informally >> know can be done to an element, as it should be and we all have done >> many times. Moreover, 2.2.3 says in the first paragraph that the >> elements are variables. >> >> So here, the compiler is too liberal, and the language would be clearer >> with an explicit rule against empty element types. >> >> I haven't spotted anywhere a parameter is specifically called a variable, >> and it is not required to have a nonempty type in the description of >> parameter declarations. However, it certainly seems to me to fit >> the definition of variable, and as above, there are lots of things >> we know can be done with it that the language simply describes as >> doable to a variable. Moreover, for every mode, there is a rule >> that at call time, the formal is "bound to" a variable, which pretty >> well makes it variable in any context where it can be used. Even in >> a keyword binding, we are getting ready to bind it to a variable >> very soon. >> >> So maybe we need to 1) say a formal parameter is a variable, and >> 2) say the type in a parameter declaration must be nonempty. >> >> The language definition is also full of an ambiguity in its use >> of "variable" that I have been bothered by in talking about programming >> languages in general for years. One meaning is the meaning I have been >> talking about, The other is the kind of variable that is declared by a >> VAR declaration (not a VAR parameter). There are some uses in the >> language that I think need to have this latter meaning in order to be right. >> >> So we need a different or qualified term for this narrower meaning. >> >> On 05/23/2011 11:54 AM, Tony Hosking wrote: >>> >>> On May 23, 2011, at 12:45 PM, Rodney M. Bates wrote: >>> >>>> On 05/23/2011 09:31 AM, Tony Hosking wrote: >>>>> An empty subrange gives a warning in the compiler. >>>> >>>> By my experiments, empty subrange, empty enumeration, and arrays >>>> thereof don't warn. >>> >>> Sorry yes, you're right. But usage to declare any variable does. >>> >>>> >>>>> But, the semantics is that it is empty, and has no values of the type. >>>>> You cannot allocate (NEW) an empty type. >>>>> You cannot declare a field of empty type. >>>> >>>> It seems odd that we have this rule for fields, but no corresponding >>>> prohibition against arrays with empty element types. By experiments, >>>> cm3 allows this, for both fixed and open arrays, but treats such array >>>> types as empty types, something the language also does not say. >>>> >>>> At the least, the language and the compiler should agree with each other. >>>> Maybe records/objects and arrays should be treated consistently here? >>> >>> Yes, I suppose so. >>> >>>>> Nor can you declare a variable of empty type. >>>> >>>> Again, oddly, there is no such prohibition in the language against >>>> declaring a formal parameter of empty type. Cm3 prohibits it, >>>> and calls it a 'variable' in the error message. >>> >>> You're right, though it's not the parameter that errors but the variable associated with the parameter. >>> >>>> Again, language and compiler should agree. >>> >>> Can you point me to the relevant entries in the language spec? >>> >>>> >>>> The language also prohibits applying FIRST and LAST to the empty >>>> enumeration, but they are OK applied to an empty subrange. >>>> This makes sense, because they return values of the base type >>>> of the argument type, and such values exist for an empty subrange >>>> but not the empty enumeration, whose base type is only itself. >>>> >>>>> >>>>> On May 23, 2011, at 8:41 AM, Hendrik Boom wrote: >>>>> >>>>>> On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: >>>>>>> >>>>>>> Well, I can build the whole tree and see how many times it helps. >>>>>>> I think this is a pretty standard optimization technique. >>>>>>> Though it'd work better with compiler-derived additional information. >>>>>>> >>>>>>> I initially happened upon this idea developing test cases. >>>>>>> >>>>>>>> The code assumes the minimum of a type is less than or equal to its maximum. >>>>>>> >>>>>>> I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. >>>>>> >>>>>> What *is* the semantics of a range whose minimum is greater than its >>>>>> maximum? There plainly can't be any values in this range. How is a >>>>>> variable of this tyoe initialized? Not to some arbitrary value of the >>>>>> type, because there aren't any. I can see this type being useful to >>>>>> admit convenient generalizations -- for example, an array with n >>>>>> elements can still exist if n happens to be zero, but it seems to me >>>>>> that any code involving a value of the range for subscripts for this >>>>>> array must be simple unexecutable. >>>>>> >>>>>> Or is there some latitude available in the principle that a value of a >>>>>> variable must always be of the correct type? >>>>>> >>>>>> -- hendrik >>>>> >>>>> >>> >>> > From hosking at cs.purdue.edu Tue May 24 04:04:18 2011 From: hosking at cs.purdue.edu (Tony Hosking) Date: Mon, 23 May 2011 22:04:18 -0400 Subject: [M3devel] range analysis? In-Reply-To: <20110523225302.GA8980@topoi.pooq.com> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> <4DDA8F1A.3070207@lcwb.coop> <8C9E1E77-686F-42E0-87FA-B573A4A02CC9@cs.purdue.edu> <4DDAA6EC.8060401@lcwb.coop> <20110523225302.GA8980@topoi.pooq.com> Message-ID: On May 23, 2011, at 6:53 PM, Hendrik Boom wrote: > On Mon, May 23, 2011 at 01:26:52PM -0500, Rodney M. Bates wrote: >> This needs more thought. On the one hand, 2.2.3 on array types allows >> the explicit element type in either kind of array type definition to >> be empty, > > Well, the array might be empty, in which case no nonexistent values > would be required when the array is created. You cannot instantiate an empty array type. > >> unlike the way 2.2.4 on record types requires a field type >> to be nonempty. >> >> On the other hand, 2.2 has a general prohibition against declaring a >> variable of empty type, and it is all over the language spec that the >> elements of arrays are "variables". The general definition of variable >> in 2.1 would apply to array elements. Thre are numerous places that >> describe things that can be done with a variable that we all informally >> know can be done to an element, as it should be and we all have done >> many times. Moreover, 2.2.3 says in the first paragraph that the >> elements are variables. >> >> So here, the compiler is too liberal, and the language would be clearer >> with an explicit rule against empty element types. >> >> I haven't spotted anywhere a parameter is specifically called a variable, >> and it is not required to have a nonempty type in the description of >> parameter declarations. However, it certainly seems to me to fit >> the definition of variable, and as above, there are lots of things >> we know can be done with it that the language simply describes as >> doable to a variable. Moreover, for every mode, there is a rule >> that at call time, the formal is "bound to" a variable, which pretty >> well makes it variable in any context where it can be used. Even in >> a keyword binding, we are getting ready to bind it to a variable >> very soon. >> >> So maybe we need to 1) say a formal parameter is a variable, and >> 2) say the type in a parameter declaration must be nonempty. >> >> The language definition is also full of an ambiguity in its use >> of "variable" that I have been bothered by in talking about programming >> languages in general for years. One meaning is the meaning I have been >> talking about, The other is the kind of variable that is declared by a >> VAR declaration (not a VAR parameter). There are some uses in the >> language that I think need to have this latter meaning in order to be right. >> >> So we need a different or qualified term for this narrower meaning. >> >> On 05/23/2011 11:54 AM, Tony Hosking wrote: >>> >>> On May 23, 2011, at 12:45 PM, Rodney M. Bates wrote: >>> >>>> On 05/23/2011 09:31 AM, Tony Hosking wrote: >>>>> An empty subrange gives a warning in the compiler. >>>> >>>> By my experiments, empty subrange, empty enumeration, and arrays >>>> thereof don't warn. >>> >>> Sorry yes, you're right. But usage to declare any variable does. >>> >>>> >>>>> But, the semantics is that it is empty, and has no values of the type. >>>>> You cannot allocate (NEW) an empty type. >>>>> You cannot declare a field of empty type. >>>> >>>> It seems odd that we have this rule for fields, but no corresponding >>>> prohibition against arrays with empty element types. By experiments, >>>> cm3 allows this, for both fixed and open arrays, but treats such array >>>> types as empty types, something the language also does not say. >>>> >>>> At the least, the language and the compiler should agree with each other. >>>> Maybe records/objects and arrays should be treated consistently here? >>> >>> Yes, I suppose so. >>> >>>>> Nor can you declare a variable of empty type. >>>> >>>> Again, oddly, there is no such prohibition in the language against >>>> declaring a formal parameter of empty type. Cm3 prohibits it, >>>> and calls it a 'variable' in the error message. >>> >>> You're right, though it's not the parameter that errors but the variable associated with the parameter. >>> >>>> Again, language and compiler should agree. >>> >>> Can you point me to the relevant entries in the language spec? >>> >>>> >>>> The language also prohibits applying FIRST and LAST to the empty >>>> enumeration, but they are OK applied to an empty subrange. >>>> This makes sense, because they return values of the base type >>>> of the argument type, and such values exist for an empty subrange >>>> but not the empty enumeration, whose base type is only itself. >>>> >>>>> >>>>> On May 23, 2011, at 8:41 AM, Hendrik Boom wrote: >>>>> >>>>>> On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: >>>>>>> >>>>>>> Well, I can build the whole tree and see how many times it helps. >>>>>>> I think this is a pretty standard optimization technique. >>>>>>> Though it'd work better with compiler-derived additional information. >>>>>>> >>>>>>> I initially happened upon this idea developing test cases. >>>>>>> >>>>>>>> The code assumes the minimum of a type is less than or equal to its maximum. >>>>>>> >>>>>>> I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. >>>>>> >>>>>> What *is* the semantics of a range whose minimum is greater than its >>>>>> maximum? There plainly can't be any values in this range. How is a >>>>>> variable of this tyoe initialized? Not to some arbitrary value of the >>>>>> type, because there aren't any. I can see this type being useful to >>>>>> admit convenient generalizations -- for example, an array with n >>>>>> elements can still exist if n happens to be zero, but it seems to me >>>>>> that any code involving a value of the range for subscripts for this >>>>>> array must be simple unexecutable. >>>>>> >>>>>> Or is there some latitude available in the principle that a value of a >>>>>> variable must always be of the correct type? >>>>>> >>>>>> -- hendrik >>>>> >>>>> >>> >>> From hosking at cs.purdue.edu Tue May 24 04:04:40 2011 From: hosking at cs.purdue.edu (Tony Hosking) Date: Mon, 23 May 2011 22:04:40 -0400 Subject: [M3devel] range analysis? In-Reply-To: <20110523225508.GB8980@topoi.pooq.com> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> <4DDA8F1A.3070207@lcwb.coop> <8C9E1E77-686F-42E0-87FA-B573A4A02CC9@cs.purdue.edu> <4DDAA6EC.8060401@lcwb.coop> <45B5D160-9E80-4BB9-8411-F3976BCDC207@cs.purdue.edu> <20110523225508.GB8980@topoi.pooq.com> Message-ID: <67872FDF-2DF6-43D5-8CCD-F1E4644CA2A6@cs.purdue.edu> Element type. On May 23, 2011, at 6:55 PM, Hendrik Boom wrote: > On Mon, May 23, 2011 at 02:45:37PM -0400, Tony Hosking wrote: >> >> On May 23, 2011, at 2:26 PM, Rodney M. Bates wrote: >> >>> This needs more thought. On the one hand, 2.2.3 on array types allows >>> the explicit element type in either kind of array type definition to >>> be empty, unlike the way 2.2.4 on record types requires a field type >>> to be nonempty. >> >> I note that an array type of empty elements is itself empty and cannot be instantiated. >> >>> On the other hand, 2.2 has a general prohibition against declaring a >>> variable of empty type, and it is all over the language spec that the >>> elements of arrays are "variables". The general definition of variable >>> in 2.1 would apply to array elements. Thre are numerous places that >>> describe things that can be done with a variable that we all informally >>> know can be done to an element, as it should be and we all have done >>> many times. Moreover, 2.2.3 says in the first paragraph that the >>> elements are variables. >> >> So, it seems to me that we could simply disallow empty array elements and be within spec. > > You mean the array elements are empty? or that the element type is > empty? These are very different concepts. From hosking at cs.purdue.edu Tue May 24 04:06:34 2011 From: hosking at cs.purdue.edu (Tony Hosking) Date: Mon, 23 May 2011 22:06:34 -0400 Subject: [M3devel] range analysis? In-Reply-To: <4DDAF56D.8010505@lcwb.coop> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> <4DDA8F1A.3070207@lcwb.coop> <8C9E1E77-686F-42E0-87FA-B573A4A02CC9@cs.purdue.edu> <4DDAA6EC.8060401@lcwb.coop> <45B5D160-9E80-4BB9-8411-F3976BCDC207@cs.purdue.edu> <4DDAF56D.8010505@lcwb.coop> Message-ID: <919256C9-1773-43EC-9B62-C45883935957@cs.purdue.edu> Sorry for the terse response. Is there a proposal buried in there? On May 23, 2011, at 8:01 PM, Rodney M. Bates wrote: > > > On 05/23/2011 01:45 PM, Tony Hosking wrote: >> >> On May 23, 2011, at 2:26 PM, Rodney M. Bates wrote: >> >>> This needs more thought. On the one hand, 2.2.3 on array types allows >>> the explicit element type in either kind of array type definition to >>> be empty, unlike the way 2.2.4 on record types requires a field type >>> to be nonempty. >> >> I note that an array type of empty elements is itself empty and cannot be instantiated. >> > > Yes. > >>> On the other hand, 2.2 has a general prohibition against declaring a >>> variable of empty type, and it is all over the language spec that the >>> elements of arrays are "variables". The general definition of variable >>> in 2.1 would apply to array elements. Thre are numerous places that >>> describe things that can be done with a variable that we all informally >>> know can be done to an element, as it should be and we all have done >>> many times. Moreover, 2.2.3 says in the first paragraph that the >>> elements are variables. >> >> So, it seems to me that we could simply disallow empty array elements and be within spec. > > I agree. > >> >>> So here, the compiler is too liberal, and the language would be clearer >>> with an explicit rule against empty element types. >> >> Right. >> >>> I haven't spotted anywhere a parameter is specifically called a variable, >>> and it is not required to have a nonempty type in the description of >>> parameter declarations. However, it certainly seems to me to fit >>> the definition of variable, and as above, there are lots of things >>> we know can be done with it that the language simply describes as >>> doable to a variable. Moreover, for every mode, there is a rule >>> that at call time, the formal is "bound to" a variable, which pretty >>> well makes it variable in any context where it can be used. Even in >>> a keyword binding, we are getting ready to bind it to a variable >>> very soon. >> >> Right. >> >>> So maybe we need to 1) say a formal parameter is a variable, and >> >> A formal parameter is not in itself a variable. It's part of a type (the signature) not an implementation of that type. But every formal parameter has a corresponding variable in the body of the procedure that implements a given signature. >> >>> 2) say the type in a parameter declaration must be nonempty. >> >> This seems overwrought. I would stop simply at the variables (not the types) and let the binding of formal parameters to variables take care of the check as it currently does. >> > > My first thought was that this argument is no more or less applicable to > a procedure type containing a formal of empty type than to a record > type containing a field (which is currently defined as a variable) > of empty type. Both are just types constructed from other type(s), > to be maybe instantiated later. In the case of the record, we now > disallow the type to be constructed. Your proposal would inconsistently > allow the procedure type to be constructed but complain when an > attempt is made to instantiate it (i.e., call it) later. > > My second thought was that a procedure type with empty-typed formal > is not an empty type, because it contains the perfectly legitimate > value NIL, which of course, you can't call anyway, thus avoiding the > issue of instantiating the formal. This is an essential difference > that would justify doing it differently for records and procedures. > > My third thought is whereas you might consider such a procedure _type_ > to have just one value, if you allow the signature in a procedure > _constant_ (i.e., an ordinary procedure declaration) to have an > empty-typed formal, you now have a value of this procedure type > other than NIL. In fact, the number of such possible values is > unbounded. Does such a procedure value make any more sense than a > value of a record with an empty-typed field? > > Right now, the compiler allows the procedure type with empty-typed > formal, a variable of that type, and assignment of NIL to the variable. > But the compiler disallows the empty-typed formal in a procedure constant > (and calls the formal a "variable" in its error message.) This seems > sensible enough to me, and I suggest we document the illegality of the > signature in a procedure constant. We could only call the formal a > variable when in the signature of a procedure constant, not a procedure > type definition, otherwise the procedure type would be illegal too. > >>> The language definition is also full of an ambiguity in its use >>> of "variable" that I have been bothered by in talking about programming >>> languages in general for years. One meaning is the meaning I have been >>> talking about, The other is the kind of variable that is declared by a >>> VAR declaration (not a VAR parameter). There are some uses in the >>> language that I think need to have this latter meaning in order to be right. >> >> Can you enumerate? >> > > Yeah, but not this minute. > >>> So we need a different or qualified term for this narrower meaning. >>> >>> On 05/23/2011 11:54 AM, Tony Hosking wrote: >>>> >>>> On May 23, 2011, at 12:45 PM, Rodney M. Bates wrote: >>>> >>>>> On 05/23/2011 09:31 AM, Tony Hosking wrote: >>>>>> An empty subrange gives a warning in the compiler. >>>>> >>>>> By my experiments, empty subrange, empty enumeration, and arrays >>>>> thereof don't warn. >>>> >>>> Sorry yes, you're right. But usage to declare any variable does. >>>> >>>>> >>>>>> But, the semantics is that it is empty, and has no values of the type. >>>>>> You cannot allocate (NEW) an empty type. >>>>>> You cannot declare a field of empty type. >>>>> >>>>> It seems odd that we have this rule for fields, but no corresponding >>>>> prohibition against arrays with empty element types. By experiments, >>>>> cm3 allows this, for both fixed and open arrays, but treats such array >>>>> types as empty types, something the language also does not say. >>>>> >>>>> At the least, the language and the compiler should agree with each other. >>>>> Maybe records/objects and arrays should be treated consistently here? >>>> >>>> Yes, I suppose so. >>>> >>>>>> Nor can you declare a variable of empty type. >>>>> >>>>> Again, oddly, there is no such prohibition in the language against >>>>> declaring a formal parameter of empty type. Cm3 prohibits it, >>>>> and calls it a 'variable' in the error message. >>>> >>>> You're right, though it's not the parameter that errors but the variable associated with the parameter. >>>> >>>>> Again, language and compiler should agree. >>>> >>>> Can you point me to the relevant entries in the language spec? >>>> >>>>> >>>>> The language also prohibits applying FIRST and LAST to the empty >>>>> enumeration, but they are OK applied to an empty subrange. >>>>> This makes sense, because they return values of the base type >>>>> of the argument type, and such values exist for an empty subrange >>>>> but not the empty enumeration, whose base type is only itself. >>>>> >>>>>> >>>>>> On May 23, 2011, at 8:41 AM, Hendrik Boom wrote: >>>>>> >>>>>>> On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: >>>>>>>> >>>>>>>> Well, I can build the whole tree and see how many times it helps. >>>>>>>> I think this is a pretty standard optimization technique. >>>>>>>> Though it'd work better with compiler-derived additional information. >>>>>>>> >>>>>>>> I initially happened upon this idea developing test cases. >>>>>>>> >>>>>>>>> The code assumes the minimum of a type is less than or equal to its maximum. >>>>>>>> >>>>>>>> I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. >>>>>>> >>>>>>> What *is* the semantics of a range whose minimum is greater than its >>>>>>> maximum? There plainly can't be any values in this range. How is a >>>>>>> variable of this tyoe initialized? Not to some arbitrary value of the >>>>>>> type, because there aren't any. I can see this type being useful to >>>>>>> admit convenient generalizations -- for example, an array with n >>>>>>> elements can still exist if n happens to be zero, but it seems to me >>>>>>> that any code involving a value of the range for subscripts for this >>>>>>> array must be simple unexecutable. >>>>>>> >>>>>>> Or is there some latitude available in the principle that a value of a >>>>>>> variable must always be of the correct type? >>>>>>> >>>>>>> -- hendrik >>>>>> >>>>>> >>>> >>>> >> >> From rodney_bates at lcwb.coop Tue May 24 22:14:59 2011 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Tue, 24 May 2011 15:14:59 -0500 Subject: [M3devel] range analysis? Message-ID: <4DDC11C3.8090303@lcwb.coop> On 05/23/2011 01:45 PM, Tony Hosking wrote: > > On May 23, 2011, at 2:26 PM, Rodney M. Bates wrote: > >> This needs more thought. On the one hand, 2.2.3 on array types allows >> the explicit element type in either kind of array type definition to >> be empty, unlike the way 2.2.4 on record types requires a field type >> to be nonempty. > > I note that an array type of empty elements is itself empty and cannot be instantiated. > Yes. >> On the other hand, 2.2 has a general prohibition against declaring a >> variable of empty type, and it is all over the language spec that the >> elements of arrays are "variables". The general definition of variable >> in 2.1 would apply to array elements. Thre are numerous places that >> describe things that can be done with a variable that we all informally >> know can be done to an element, as it should be and we all have done >> many times. Moreover, 2.2.3 says in the first paragraph that the >> elements are variables. > > So, it seems to me that we could simply disallow empty array elements and be within spec. I agree. > >> So here, the compiler is too liberal, and the language would be clearer >> with an explicit rule against empty element types. > > Right. > >> I haven't spotted anywhere a parameter is specifically called a variable, >> and it is not required to have a nonempty type in the description of >> parameter declarations. However, it certainly seems to me to fit >> the definition of variable, and as above, there are lots of things >> we know can be done with it that the language simply describes as >> doable to a variable. Moreover, for every mode, there is a rule >> that at call time, the formal is "bound to" a variable, which pretty >> well makes it variable in any context where it can be used. Even in >> a keyword binding, we are getting ready to bind it to a variable >> very soon. > > Right. > >> So maybe we need to 1) say a formal parameter is a variable, and > > A formal parameter is not in itself a variable. It's part of a type (the signature) not an implementation of that type. But every formal parameter has a corresponding variable in the body of the procedure that implements a given signature. > >> 2) say the type in a parameter declaration must be nonempty. > > This seems overwrought. I would stop simply at the variables (not the types) and let the binding of formal parameters to variables take care of the check as it currently does. > My first thought was that this argument is no more or less applicable to a procedure type containing a formal of empty type than to a record type containing a field (which is currently defined as a variable) of empty type. Both are just types constructed from other type(s), to be maybe instantiated later. In the case of the record, we now disallow the type to be constructed. Your proposal would inconsistently allow the procedure type to be constructed but complain when an attempt is made to instantiate it (i.e., call it) later. My second thought was that a procedure type with empty-typed formal is not an empty type, because it contains the perfectly legitimate value NIL, which of course, you can't call anyway, thus avoiding the issue of instantiating the formal. This is an essential difference that would justify doing it differently for records and procedures. My third thought is whereas you might consider such a procedure _type_ to have just one value, if you allow the signature in a procedure _constant_ (i.e., an ordinary procedure declaration) to have an empty-typed formal, you now have a value of this procedure type other than NIL. In fact, the number of such possible values is unbounded. Does such a procedure value make any more sense than a value of a record with an empty-typed field? Right now, the compiler allows the procedure type with empty-typed formal, a variable of that type, and assignment of NIL to the variable. But the compiler disallows the empty-typed formal in a procedure constant (and calls the formal a "variable" in its error message.) This seems sensible enough to me, and I suggest we document the illegality of the signature in a procedure constant. We could only call the formal a variable when in the signature of a procedure constant, not a procedure type definition, otherwise the procedure type would be illegal too. >> The language definition is also full of an ambiguity in its use >> of "variable" that I have been bothered by in talking about programming >> languages in general for years. One meaning is the meaning I have been >> talking about, The other is the kind of variable that is declared by a >> VAR declaration (not a VAR parameter). There are some uses in the >> language that I think need to have this latter meaning in order to be right. > > Can you enumerate? > Yeah, but not this minute. >> So we need a different or qualified term for this narrower meaning. >> >> On 05/23/2011 11:54 AM, Tony Hosking wrote: >>> >>> On May 23, 2011, at 12:45 PM, Rodney M. Bates wrote: >>> >>>> On 05/23/2011 09:31 AM, Tony Hosking wrote: >>>>> An empty subrange gives a warning in the compiler. >>>> >>>> By my experiments, empty subrange, empty enumeration, and arrays >>>> thereof don't warn. >>> >>> Sorry yes, you're right. But usage to declare any variable does. >>> >>>> >>>>> But, the semantics is that it is empty, and has no values of the type. >>>>> You cannot allocate (NEW) an empty type. >>>>> You cannot declare a field of empty type. >>>> >>>> It seems odd that we have this rule for fields, but no corresponding >>>> prohibition against arrays with empty element types. By experiments, >>>> cm3 allows this, for both fixed and open arrays, but treats such array >>>> types as empty types, something the language also does not say. >>>> >>>> At the least, the language and the compiler should agree with each other. >>>> Maybe records/objects and arrays should be treated consistently here? >>> >>> Yes, I suppose so. >>> >>>>> Nor can you declare a variable of empty type. >>>> >>>> Again, oddly, there is no such prohibition in the language against >>>> declaring a formal parameter of empty type. Cm3 prohibits it, >>>> and calls it a 'variable' in the error message. >>> >>> You're right, though it's not the parameter that errors but the variable associated with the parameter. >>> >>>> Again, language and compiler should agree. >>> >>> Can you point me to the relevant entries in the language spec? >>> >>>> >>>> The language also prohibits applying FIRST and LAST to the empty >>>> enumeration, but they are OK applied to an empty subrange. >>>> This makes sense, because they return values of the base type >>>> of the argument type, and such values exist for an empty subrange >>>> but not the empty enumeration, whose base type is only itself. >>>> >>>>> >>>>> On May 23, 2011, at 8:41 AM, Hendrik Boom wrote: >>>>> >>>>>> On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: >>>>>>> >>>>>>> Well, I can build the whole tree and see how many times it helps. >>>>>>> I think this is a pretty standard optimization technique. >>>>>>> Though it'd work better with compiler-derived additional information. >>>>>>> >>>>>>> I initially happened upon this idea developing test cases. >>>>>>> >>>>>>>> The code assumes the minimum of a type is less than or equal to its maximum. >>>>>>> >>>>>>> I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. >>>>>> >>>>>> What *is* the semantics of a range whose minimum is greater than its >>>>>> maximum? There plainly can't be any values in this range. How is a >>>>>> variable of this tyoe initialized? Not to some arbitrary value of the >>>>>> type, because there aren't any. I can see this type being useful to >>>>>> admit convenient generalizations -- for example, an array with n >>>>>> elements can still exist if n happens to be zero, but it seems to me >>>>>> that any code involving a value of the range for subscripts for this >>>>>> array must be simple unexecutable. >>>>>> >>>>>> Or is there some latitude available in the principle that a value of a >>>>>> variable must always be of the correct type? >>>>>> >>>>>> -- hendrik >>>>> >>>>> >>> >>> > From mika at async.caltech.edu Tue May 24 22:21:50 2011 From: mika at async.caltech.edu (Mika Nystrom) Date: Tue, 24 May 2011 13:21:50 -0700 Subject: [M3devel] range analysis? In-Reply-To: <4DDC11C3.8090303@lcwb.coop> References: <4DDC11C3.8090303@lcwb.coop> Message-ID: <20110524202150.5B4711A2078@async.async.caltech.edu> "Rodney M. Bates" writes: ... > >My first thought was that this argument is no more or less applicable to >a procedure type containing a formal of empty type than to a record >type containing a field (which is currently defined as a variable) >of empty type. Both are just types constructed from other type(s), >to be maybe instantiated later. In the case of the record, we now >disallow the type to be constructed. Your proposal would inconsistently >allow the procedure type to be constructed but complain when an >attempt is made to instantiate it (i.e., call it) later. > >My second thought was that a procedure type with empty-typed formal >is not an empty type, because it contains the perfectly legitimate >value NIL, which of course, you can't call anyway, thus avoiding the >issue of instantiating the formal. This is an essential difference >that would justify doing it differently for records and procedures. > By this logic, shoudln't you also allow such types to be fields in OBJECT types? What about REF RECORD types? Mika From rodney_bates at lcwb.coop Wed May 25 16:54:01 2011 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Wed, 25 May 2011 09:54:01 -0500 Subject: [M3devel] range analysis? In-Reply-To: <919256C9-1773-43EC-9B62-C45883935957@cs.purdue.edu> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> <4DDA8F1A.3070207@lcwb.coop> <8C9E1E77-686F-42E0-87FA-B573A4A02CC9@cs.purdue.edu> <4DDAA6EC.8060401@lcwb.coop> <45B5D160-9E80-4BB9-8411-F3976BCDC207@cs.purdue.edu> <4DDAF56D.8010505@lcwb.coop> <919256C9-1773-43EC-9B62-C45883935957@cs.purdue.edu> Message-ID: <4DDD1809.3030108@lcwb.coop> Yes. Keep the current behavior of the compiler (formal with empty-type is legal in a procedure type, but not in a procedure constant) and document it. On 05/23/2011 09:06 PM, Tony Hosking wrote: > Sorry for the terse response. Is there a proposal buried in there? > > On May 23, 2011, at 8:01 PM, Rodney M. Bates wrote: > >> >> >> On 05/23/2011 01:45 PM, Tony Hosking wrote: >>> >>> On May 23, 2011, at 2:26 PM, Rodney M. Bates wrote: >>> >>>> This needs more thought. On the one hand, 2.2.3 on array types allows >>>> the explicit element type in either kind of array type definition to >>>> be empty, unlike the way 2.2.4 on record types requires a field type >>>> to be nonempty. >>> >>> I note that an array type of empty elements is itself empty and cannot be instantiated. >>> >> >> Yes. >> >>>> On the other hand, 2.2 has a general prohibition against declaring a >>>> variable of empty type, and it is all over the language spec that the >>>> elements of arrays are "variables". The general definition of variable >>>> in 2.1 would apply to array elements. Thre are numerous places that >>>> describe things that can be done with a variable that we all informally >>>> know can be done to an element, as it should be and we all have done >>>> many times. Moreover, 2.2.3 says in the first paragraph that the >>>> elements are variables. >>> >>> So, it seems to me that we could simply disallow empty array elements and be within spec. >> >> I agree. >> >>> >>>> So here, the compiler is too liberal, and the language would be clearer >>>> with an explicit rule against empty element types. >>> >>> Right. >>> >>>> I haven't spotted anywhere a parameter is specifically called a variable, >>>> and it is not required to have a nonempty type in the description of >>>> parameter declarations. However, it certainly seems to me to fit >>>> the definition of variable, and as above, there are lots of things >>>> we know can be done with it that the language simply describes as >>>> doable to a variable. Moreover, for every mode, there is a rule >>>> that at call time, the formal is "bound to" a variable, which pretty >>>> well makes it variable in any context where it can be used. Even in >>>> a keyword binding, we are getting ready to bind it to a variable >>>> very soon. >>> >>> Right. >>> >>>> So maybe we need to 1) say a formal parameter is a variable, and >>> >>> A formal parameter is not in itself a variable. It's part of a type (the signature) not an implementation of that type. But every formal parameter has a corresponding variable in the body of the procedure that implements a given signature. >>> >>>> 2) say the type in a parameter declaration must be nonempty. >>> >>> This seems overwrought. I would stop simply at the variables (not the types) and let the binding of formal parameters to variables take care of the check as it currently does. >>> >> >> My first thought was that this argument is no more or less applicable to >> a procedure type containing a formal of empty type than to a record >> type containing a field (which is currently defined as a variable) >> of empty type. Both are just types constructed from other type(s), >> to be maybe instantiated later. In the case of the record, we now >> disallow the type to be constructed. Your proposal would inconsistently >> allow the procedure type to be constructed but complain when an >> attempt is made to instantiate it (i.e., call it) later. >> >> My second thought was that a procedure type with empty-typed formal >> is not an empty type, because it contains the perfectly legitimate >> value NIL, which of course, you can't call anyway, thus avoiding the >> issue of instantiating the formal. This is an essential difference >> that would justify doing it differently for records and procedures. >> >> My third thought is whereas you might consider such a procedure _type_ >> to have just one value, if you allow the signature in a procedure >> _constant_ (i.e., an ordinary procedure declaration) to have an >> empty-typed formal, you now have a value of this procedure type >> other than NIL. In fact, the number of such possible values is >> unbounded. Does such a procedure value make any more sense than a >> value of a record with an empty-typed field? >> >> Right now, the compiler allows the procedure type with empty-typed >> formal, a variable of that type, and assignment of NIL to the variable. >> But the compiler disallows the empty-typed formal in a procedure constant >> (and calls the formal a "variable" in its error message.) This seems >> sensible enough to me, and I suggest we document the illegality of the >> signature in a procedure constant. We could only call the formal a >> variable when in the signature of a procedure constant, not a procedure >> type definition, otherwise the procedure type would be illegal too. >> >>>> The language definition is also full of an ambiguity in its use >>>> of "variable" that I have been bothered by in talking about programming >>>> languages in general for years. One meaning is the meaning I have been >>>> talking about, The other is the kind of variable that is declared by a >>>> VAR declaration (not a VAR parameter). There are some uses in the >>>> language that I think need to have this latter meaning in order to be right. >>> >>> Can you enumerate? >>> >> >> Yeah, but not this minute. >> >>>> So we need a different or qualified term for this narrower meaning. >>>> >>>> On 05/23/2011 11:54 AM, Tony Hosking wrote: >>>>> >>>>> On May 23, 2011, at 12:45 PM, Rodney M. Bates wrote: >>>>> >>>>>> On 05/23/2011 09:31 AM, Tony Hosking wrote: >>>>>>> An empty subrange gives a warning in the compiler. >>>>>> >>>>>> By my experiments, empty subrange, empty enumeration, and arrays >>>>>> thereof don't warn. >>>>> >>>>> Sorry yes, you're right. But usage to declare any variable does. >>>>> >>>>>> >>>>>>> But, the semantics is that it is empty, and has no values of the type. >>>>>>> You cannot allocate (NEW) an empty type. >>>>>>> You cannot declare a field of empty type. >>>>>> >>>>>> It seems odd that we have this rule for fields, but no corresponding >>>>>> prohibition against arrays with empty element types. By experiments, >>>>>> cm3 allows this, for both fixed and open arrays, but treats such array >>>>>> types as empty types, something the language also does not say. >>>>>> >>>>>> At the least, the language and the compiler should agree with each other. >>>>>> Maybe records/objects and arrays should be treated consistently here? >>>>> >>>>> Yes, I suppose so. >>>>> >>>>>>> Nor can you declare a variable of empty type. >>>>>> >>>>>> Again, oddly, there is no such prohibition in the language against >>>>>> declaring a formal parameter of empty type. Cm3 prohibits it, >>>>>> and calls it a 'variable' in the error message. >>>>> >>>>> You're right, though it's not the parameter that errors but the variable associated with the parameter. >>>>> >>>>>> Again, language and compiler should agree. >>>>> >>>>> Can you point me to the relevant entries in the language spec? >>>>> >>>>>> >>>>>> The language also prohibits applying FIRST and LAST to the empty >>>>>> enumeration, but they are OK applied to an empty subrange. >>>>>> This makes sense, because they return values of the base type >>>>>> of the argument type, and such values exist for an empty subrange >>>>>> but not the empty enumeration, whose base type is only itself. >>>>>> >>>>>>> >>>>>>> On May 23, 2011, at 8:41 AM, Hendrik Boom wrote: >>>>>>> >>>>>>>> On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: >>>>>>>>> >>>>>>>>> Well, I can build the whole tree and see how many times it helps. >>>>>>>>> I think this is a pretty standard optimization technique. >>>>>>>>> Though it'd work better with compiler-derived additional information. >>>>>>>>> >>>>>>>>> I initially happened upon this idea developing test cases. >>>>>>>>> >>>>>>>>>> The code assumes the minimum of a type is less than or equal to its maximum. >>>>>>>>> >>>>>>>>> I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. >>>>>>>> >>>>>>>> What *is* the semantics of a range whose minimum is greater than its >>>>>>>> maximum? There plainly can't be any values in this range. How is a >>>>>>>> variable of this tyoe initialized? Not to some arbitrary value of the >>>>>>>> type, because there aren't any. I can see this type being useful to >>>>>>>> admit convenient generalizations -- for example, an array with n >>>>>>>> elements can still exist if n happens to be zero, but it seems to me >>>>>>>> that any code involving a value of the range for subscripts for this >>>>>>>> array must be simple unexecutable. >>>>>>>> >>>>>>>> Or is there some latitude available in the principle that a value of a >>>>>>>> variable must always be of the correct type? >>>>>>>> >>>>>>>> -- hendrik >>>>>>> >>>>>>> >>>>> >>>>> >>> >>> > > From rodney_bates at lcwb.coop Wed May 25 17:55:11 2011 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Wed, 25 May 2011 10:55:11 -0500 Subject: [M3devel] range analysis? In-Reply-To: <20110524202150.5B4711A2078@async.async.caltech.edu> References: <4DDC11C3.8090303@lcwb.coop> <20110524202150.5B4711A2078@async.async.caltech.edu> Message-ID: <4DDD265F.3020102@lcwb.coop> On 05/24/2011 03:21 PM, Mika Nystrom wrote: > "Rodney M. Bates" writes: > ... >> >> My first thought was that this argument is no more or less applicable to >> a procedure type containing a formal of empty type than to a record >> type containing a field (which is currently defined as a variable) >> of empty type. Both are just types constructed from other type(s), >> to be maybe instantiated later. In the case of the record, we now >> disallow the type to be constructed. Your proposal would inconsistently >> allow the procedure type to be constructed but complain when an >> attempt is made to instantiate it (i.e., call it) later. >> >> My second thought was that a procedure type with empty-typed formal >> is not an empty type, because it contains the perfectly legitimate >> value NIL, which of course, you can't call anyway, thus avoiding the >> issue of instantiating the formal. This is an essential difference >> that would justify doing it differently for records and procedures. >> > > By this logic, shoudln't you also allow such types to be fields > in OBJECT types? Yes. But neither the language nor the compiler allow this. The compiler gives no error on subsequent attempt to allocate such an object, but this is probably just secondary. What about REF RECORD types? REF EmptyType is OK, and the compiler allows it to be defined but not allocated. But the only ways right now to get an empty type are an empty enumeration, empty subrange, or array of empty-typed elements. Try to construct a record with an empty-typed field and the type definition fails. I am doing more compiler experiments and language reading. It looks like we have some inconsistencies. > > Mika > From dabenavidesd at yahoo.es Wed May 25 18:30:51 2011 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Wed, 25 May 2011 17:30:51 +0100 (BST) Subject: [M3devel] range analysis? In-Reply-To: <4DDD265F.3020102@lcwb.coop> Message-ID: <812997.17365.qm@web29709.mail.ird.yahoo.com> Hi all: well that said, please you may take a look at this manual (from p8): http://research.microsoft.com/en-us/um/people/blampson/32a-CedarLang/32a-CedarLangOCR.doc Modula-3 has an action semantics description (not very notorious): http://www.dcs.gla.ac.uk/~daw/publications/M3AS.ps And in the same way: http://research.microsoft.com/en-us/um/people/blampson/48-POCScourse/48-POCS2006.pdf page 24 Thanks in advance, hope it helps a bit --- El mi?, 25/5/11, Rodney M. Bates escribi?: > De: Rodney M. Bates > Asunto: Re: [M3devel] range analysis? > Para: m3devel at elegosoft.com > Fecha: mi?rcoles, 25 de mayo, 2011 10:55 > > > On 05/24/2011 03:21 PM, Mika Nystrom wrote: > > "Rodney M. Bates" writes: > > ... > >> > >> My first thought was that this argument is no more > or less applicable to > >> a procedure type containing a formal of empty type > than to a record > >> type containing a field (which is currently > defined as a variable) > >> of empty type. Both are just types > constructed from other type(s), > >> to be maybe instantiated later. In the case > of the record, we now > >> disallow the type to be constructed. Your > proposal would inconsistently > >> allow the procedure type to be constructed but > complain when an > >> attempt is made to instantiate it (i.e., call it) > later. > >> > >> My second thought was that a procedure type with > empty-typed formal > >> is not an empty type, because it contains the > perfectly legitimate > >> value NIL, which of course, you can't call anyway, > thus avoiding the > >> issue of instantiating the formal. This is > an essential difference > >> that would justify doing it differently for > records and procedures. > >> > > > > By this logic, shoudln't you also allow such types to > be fields > > in OBJECT types? > > Yes. But neither the language nor the compiler allow > this. The > compiler gives no error on subsequent attempt to allocate > such an object, > but this is probably just secondary. > > What about REF RECORD types? > > REF EmptyType is OK, and the compiler allows it to be > defined > but not allocated. But the only ways right now to get > an empty > type are an empty enumeration, empty subrange, or array of > empty-typed elements. Try to construct a record with > an > empty-typed field and the type definition fails. > > I am doing more compiler experiments and language reading. > It looks like we have some inconsistencies. > > > > > Mika > > > From dabenavidesd at yahoo.es Thu May 26 00:38:34 2011 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Wed, 25 May 2011 23:38:34 +0100 (BST) Subject: [M3devel] About modula3.org and modula-3 domain Message-ID: <36867.43808.qm@web29703.mail.ird.yahoo.com> Hi all: has anyone devised an opportunity to have it, or if it is of any help, when would one become important one doesn't know (important for others than us), then if so what do you think and (are you) waiting? :) If any interest in others please if you speak up (e.g .com, et al). Thanks in advance From dabenavidesd at yahoo.es Fri May 27 05:18:16 2011 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Fri, 27 May 2011 04:18:16 +0100 (BST) Subject: [M3devel] About modula3.org and modula-3 domain In-Reply-To: <36867.43808.qm@web29703.mail.ird.yahoo.com> Message-ID: <161903.96505.qm@web29710.mail.ird.yahoo.com> Hi all: and please start to think where we want to go, all your wildest Modula dreams might become true: http://www.ic.unicamp.br/~stolfi/PUB/misc/misc/ramblings/comp/modula/M3-99Wishes.msg http://www.ic.unicamp.br/~stolfi/PUB/misc/misc/ramblings/comp/ReversingGuardedPrograms.mgs http://www.ic.unicamp.br/~stolfi/PUB/misc/misc/ramblings/comp/ReversingGuardedPrograms.mgs Yeah, type inference, plus guarded commands built into language and some Modula-3 Modula type generics type reconstruction before compile time (type checking), and then object generics, who wants to work for (much of this currently solved, who can say about that any other language)? So, maybe its more profitable to start deploying modula4 modula-4 dot com, co, etc at al. I guess you would believe it. PS Finally, all type checking type inferencer and verfication condition generator sound and why not heck complete (so everything is always true it's safe and not UNSAFE) Thanks in advance --- El mi?, 25/5/11, Daniel Alejandro Benavides D. escribi?: > De: Daniel Alejandro Benavides D. > Asunto: [M3devel] About modula3.org and modula-3 domain > Para: m3devel at elegosoft.com > Fecha: mi?rcoles, 25 de mayo, 2011 17:38 > Hi all: > has anyone devised an opportunity to have it, or if it is > of any help, when would one become important one doesn't > know (important for others than us), then if so what do you > think and (are you) waiting? :) > If any interest in others please if you speak up (e.g .com, > et al). > Thanks in advance > From dabenavidesd at yahoo.es Tue May 31 22:12:52 2011 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Tue, 31 May 2011 21:12:52 +0100 (BST) Subject: [M3devel] About modula3.org and modula-3 domain In-Reply-To: <161903.96505.qm@web29710.mail.ird.yahoo.com> Message-ID: <850866.31542.qm@web29713.mail.ird.yahoo.com> Hi all: well, instead of redirection, what about mirroring? We have already a public machine here to do that (first ip #, later another domain I guess or), which ports will we needed to open (does dcvs installation help)? Thanks in advance --- El jue, 26/5/11, Daniel Alejandro Benavides D. escribi?: > De: Daniel Alejandro Benavides D. > Asunto: Re: [M3devel] About modula3.org and modula-3 domain > Para: m3devel at elegosoft.com > Fecha: jueves, 26 de mayo, 2011 22:18 > Hi all: > and please start to think where we want to go, all your > wildest Modula dreams might become true: > http://www.ic.unicamp.br/~stolfi/PUB/misc/misc/ramblings/comp/modula/M3-99Wishes.msg > > http://www.ic.unicamp.br/~stolfi/PUB/misc/misc/ramblings/comp/ReversingGuardedPrograms.mgs > > http://www.ic.unicamp.br/~stolfi/PUB/misc/misc/ramblings/comp/ReversingGuardedPrograms.mgs > > Yeah, type inference, plus guarded commands built into > language and some Modula-3 Modula type generics type > reconstruction before compile time (type checking), and then > object generics, who wants to work for (much of this > currently solved, who can say about that any other > language)? > > So, maybe its more profitable to start deploying modula4 > modula-4 dot com, co, etc at al. I guess you would believe > it. > > PS Finally, all type checking type inferencer and > verfication condition generator sound and why not heck > complete (so everything is always true it's safe and not > UNSAFE) > > Thanks in advance > > --- El mi?, 25/5/11, Daniel Alejandro Benavides D. > escribi?: > > > De: Daniel Alejandro Benavides D. > > Asunto: [M3devel] About modula3.org and modula-3 > domain > > Para: m3devel at elegosoft.com > > Fecha: mi?rcoles, 25 de mayo, 2011 17:38 > > Hi all: > > has anyone devised an opportunity to have it, or if it > is > > of any help, when would one become important one > doesn't > > know (important for others than us), then if so what > do you > > think and (are you) waiting? :) > > If any interest in others please if you speak up (e.g > .com, > > et al). > > Thanks in advance > > > From rcolebur at SCIRES.COM Sun May 15 05:57:06 2011 From: rcolebur at SCIRES.COM (Coleburn, Randy) Date: Sat, 14 May 2011 23:57:06 -0400 Subject: [M3devel] stubgen problem with m3-tools\m3tk\src\toolmisc\M3Error.m3 line 214 Message-ID: I am seeing a new error when building on Windows 2000, XP, and 7. The error affects at least the following packages: * zeus * obliqrt * obliqparse * juno-app The problem is manifested when running the stub generator (stubgen). In all cases it reports a runtime error, attempt to reference an illegal memory location, and the file and line reference is always to line #214 in m3-tools\m3tk\src\toolmisc\M3Error.m3 I suspect some recent change is the culprit. Here is an example of the error when building juno-app: C:\cm3\bin\stubgen -v1 -sno RemoteView.T -T.M3IMPTAB *** *** runtime error: *** Attempt to reference an illegal memory location. *** file "..\src\toolmisc\M3Error.m3", line 214 *** Stack trace: FP PC Procedure --------- --------- ------------------------------- 0x37f208 0xdd496c CarefulNodeLookup + 0x1e in ..\src\toolmisc\M3Error.m3 0x37f26c 0xdd4401 RecordError + 0x2e8 in ..\src\toolmisc\M3Error.m3 0x37f298 0xdd4026 Report + 0x23 in ..\src\toolmisc\M3Error.m3 0x37f308 0xe46703 Eval + 0x220 in ..\src\sem\M3CExpValue.m3 0x37f358 0xe48773 Set + 0x672 in ..\src\sem\M3CExpValue.m3 0x37f380 0xda645b DoVisit + 0x121 in ..\src\gast\ASTWalk.m3 0x37f3a4 0xe381de Range + 0x85 in ..\src\ast\M3AST_AS_Walk.m3 0x37f3c8 0xda63e8 DoVisit + 0xae in ..\src\gast\ASTWalk.m3 0x37f3ec 0xe36a81 Subrange_type + 0x85 in ..\src\ast\M3AST_AS_Walk.m3 0x37f410 0xda63e8 DoVisit + 0xae in ..\src\gast\ASTWalk.m3 ......... ......... ... more frames ... "C:\cm3\pkg\netobj\src\netobj.tmpl", line 37: quake runtime error: exit 2147483647: C:\cm3\bin\stubgen -v1 -sno RemoteView.T -T.M3IMPTAB --procedure-- -line- -file--- exec -- _v_netobj 37 C:\cm3\pkg\netobj\src\netobj.tmpl netobjv1 44 C:\cm3\pkg\netobj\src\netobj.tmpl netobj 64 C:\cm3\pkg\netobj\src\netobj.tmpl include_dir 105 C:\cm3\Sandbox\m3-ui\juno-2\juno-app\src\m3makefile 4 C:\cm3\Sandbox\m3-ui\juno-2\juno-app\NT386\m3make.args Fatal Error: package build failed WARNING: Encountered an error when processing package "m3-ui\juno-2\juno-app" for "-build". Regards, Randy Coleburn -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Sun May 15 15:46:14 2011 From: hosking at cs.purdue.edu (Tony Hosking) Date: Sun, 15 May 2011 09:46:14 -0400 Subject: [M3devel] stubgen problem with m3-tools\m3tk\src\toolmisc\M3Error.m3 line 214 In-Reply-To: References: Message-ID: There have been recent changes to m3tk. I think by Mika? Sent from my iPad On 14/05/2011, at 11:57 PM, "Coleburn, Randy" wrote: > I am seeing a new error when building on Windows 2000, XP, and 7. > > > > The error affects at least the following packages: > > ? zeus > > ? obliqrt > > ? obliqparse > > ? juno-app > > > > The problem is manifested when running the stub generator (stubgen). In all cases it reports a runtime error, attempt to reference an illegal memory location, and the file and line reference is always to line #214 in m3-tools\m3tk\src\toolmisc\M3Error.m3 > > > > I suspect some recent change is the culprit. > > > > Here is an example of the error when building juno-app: > > > > C:\cm3\bin\stubgen -v1 -sno RemoteView.T -T.M3IMPTAB > > > > > > *** > > *** runtime error: > > *** Attempt to reference an illegal memory location. > > *** file "..\src\toolmisc\M3Error.m3", line 214 > > *** > > > > Stack trace: > > FP PC Procedure > > --------- --------- ------------------------------- > > 0x37f208 0xdd496c CarefulNodeLookup + 0x1e in ..\src\toolmisc\M3Error.m3 > > 0x37f26c 0xdd4401 RecordError + 0x2e8 in ..\src\toolmisc\M3Error.m3 > > 0x37f298 0xdd4026 Report + 0x23 in ..\src\toolmisc\M3Error.m3 > > 0x37f308 0xe46703 Eval + 0x220 in ..\src\sem\M3CExpValue.m3 > > 0x37f358 0xe48773 Set + 0x672 in ..\src\sem\M3CExpValue.m3 > > 0x37f380 0xda645b DoVisit + 0x121 in ..\src\gast\ASTWalk.m3 > > 0x37f3a4 0xe381de Range + 0x85 in ..\src\ast\M3AST_AS_Walk.m3 > > 0x37f3c8 0xda63e8 DoVisit + 0xae in ..\src\gast\ASTWalk.m3 > > 0x37f3ec 0xe36a81 Subrange_type + 0x85 in ..\src\ast\M3AST_AS_Walk.m3 > > 0x37f410 0xda63e8 DoVisit + 0xae in ..\src\gast\ASTWalk.m3 > > ......... ......... ... more frames ... > > "C:\cm3\pkg\netobj\src\netobj.tmpl", line 37: quake runtime error: exit 2147483647: C:\cm3\bin\stubgen -v1 -sno RemoteView.T -T.M3IMPTAB > > > > --procedure-- -line- -file--- > > exec -- > > _v_netobj 37 C:\cm3\pkg\netobj\src\netobj.tmpl > > netobjv1 44 C:\cm3\pkg\netobj\src\netobj.tmpl > > netobj 64 C:\cm3\pkg\netobj\src\netobj.tmpl > > include_dir 105 C:\cm3\Sandbox\m3-ui\juno-2\juno-app\src\m3makefile > > 4 C:\cm3\Sandbox\m3-ui\juno-2\juno-app\NT386\m3make.args > > > > Fatal Error: package build failed > > > > WARNING: Encountered an error when processing package "m3-ui\juno-2\juno-app" for "-build". > > > > Regards, > > Randy Coleburn -------------- next part -------------- An HTML attachment was scrubbed... URL: From rodney_bates at lcwb.coop Sun May 15 19:08:21 2011 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Sun, 15 May 2011 12:08:21 -0500 Subject: [M3devel] stubgen problem with m3-tools\m3tk\src\toolmisc\M3Error.m3 line 214 In-Reply-To: References: Message-ID: <4DD00885.7040006@lcwb.coop> Hmm, I checked in a change to the head on 2011-4-26 that could lie right on this backtrace. It is in M3CExpValue.Eval, and contains a call on M3Error.Report. There are several other calls in M3CExpValue.Eval to M3Error.Report, not involving my change. Simple proportioning between hex displacements and source line counts suggests it is the call in the change. But it is hard to image how my change could do anything but reduce the set of cases where this call is executed, and any such cases remaining sould have been with the same values of all variables, compared to before. Moreover, this or any of the calls in Eval on Report would have been producing error messages before the change. I presume there were no such error messages formerly? Are there any LONGINT literals in the code stubgen is being run on? The change only weakens an overzealous error check for them. On 05/14/2011 10:57 PM, Coleburn, Randy wrote: > I am seeing a new error when building on Windows 2000, XP, and 7. > > The error affects at least the following packages: > > ?zeus > > ?obliqrt > > ?obliqparse > > ?juno-app > > The problem is manifested when running the stub generator (stubgen). In all cases it reports a runtime error, attempt to reference an illegal memory location, and the file and line reference is always to line #*214* in *m3-tools\m3tk\src\toolmisc\M3Error.m3* > > I suspect some recent change is the culprit. > > Here is an example of the error when building juno-app: > > C:\cm3\bin\stubgen -v1 -sno RemoteView.T -T.M3IMPTAB > > *** > > *** runtime error: > > *** Attempt to reference an illegal memory location. > > *** file "..\src\toolmisc\M3Error.m3", line 214 > > *** > > Stack trace: > > FP PC Procedure > > --------- --------- ------------------------------- > > 0x37f208 0xdd496c CarefulNodeLookup + 0x1e in ..\src\toolmisc\M3Error.m3 > > 0x37f26c 0xdd4401 RecordError + 0x2e8 in ..\src\toolmisc\M3Error.m3 > > 0x37f298 0xdd4026 Report + 0x23 in ..\src\toolmisc\M3Error.m3 > > 0x37f308 0xe46703 Eval + 0x220 in ..\src\sem\M3CExpValue.m3 > > 0x37f358 0xe48773 Set + 0x672 in ..\src\sem\M3CExpValue.m3 > > 0x37f380 0xda645b DoVisit + 0x121 in ..\src\gast\ASTWalk.m3 > > 0x37f3a4 0xe381de Range + 0x85 in ..\src\ast\M3AST_AS_Walk.m3 > > 0x37f3c8 0xda63e8 DoVisit + 0xae in ..\src\gast\ASTWalk.m3 > > 0x37f3ec 0xe36a81 Subrange_type + 0x85 in ..\src\ast\M3AST_AS_Walk.m3 > > 0x37f410 0xda63e8 DoVisit + 0xae in ..\src\gast\ASTWalk.m3 > > ......... ......... ... more frames ... > > "C:\cm3\pkg\netobj\src\netobj.tmpl", line 37: quake runtime error: exit 2147483647: C:\cm3\bin\stubgen -v1 -sno RemoteView.T -T.M3IMPTAB > > --procedure-- -line- -file--- > > exec -- > > _v_netobj 37 C:\cm3\pkg\netobj\src\netobj.tmpl > > netobjv1 44 C:\cm3\pkg\netobj\src\netobj.tmpl > > netobj 64 C:\cm3\pkg\netobj\src\netobj.tmpl > > include_dir 105 C:\cm3\Sandbox\m3-ui\juno-2\juno-app\src\m3makefile > > 4 C:\cm3\Sandbox\m3-ui\juno-2\juno-app\NT386\m3make.args > > Fatal Error: package build failed > > WARNING: Encountered an error when processing package "m3-ui\juno-2\juno-app" for "-build". > > Regards, > > Randy Coleburn > From mika at async.caltech.edu Sun May 15 19:23:22 2011 From: mika at async.caltech.edu (Mika Nystrom) Date: Sun, 15 May 2011 10:23:22 -0700 Subject: [M3devel] stubgen problem with m3-tools\m3tk\src\toolmisc\M3Error.m3 line 214 In-Reply-To: <4DD00885.7040006@lcwb.coop> References: <4DD00885.7040006@lcwb.coop> Message-ID: <20110515172322.0D5AC1A2078@async.async.caltech.edu> Stupid question: you did "make clean" (or equivalent) first, right? I've noticed CM3 is pretty bad about detecting changes (at least compared to PM3, which is my basis for all Modula-3 comparisons) and can easily make corrupted binaries if you change things and rely on incremental compilation---at least. if an interface has changed, which I suppose extends to opaque information too. BTW, I have reviewing the LONGINT/m3tk change and Jay's -pthread change on my todo list. CM3 just has been pushed down a bit for a while, hope to get to them soon, not ignoring you guys. Looks to me like something is forgetting to call M3Error.SetCu. Not code I've ever gone near... Mika "Rodney M. Bates" writes: >Hmm, I checked in a change to the head on 2011-4-26 that could lie right on >this backtrace. It is in M3CExpValue.Eval, and contains a call on M3Error.Rep >ort. >There are several other calls in M3CExpValue.Eval to M3Error.Report, not invol >ving >my change. Simple proportioning between hex displacements and source line cou >nts >suggests it is the call in the change. > >But it is hard to image how my change could do anything but reduce the set of >cases where this call is executed, and any such cases remaining sould have bee >n >with the same values of all variables, compared to before. > >Moreover, this or any of the calls in Eval on Report would have been producing >error messages before the change. I presume there were no such error messages >formerly? > >Are there any LONGINT literals in the code stubgen is being run on? The chang >e >only weakens an overzealous error check for them. > >On 05/14/2011 10:57 PM, Coleburn, Randy wrote: >> I am seeing a new error when building on Windows 2000, XP, and 7. >> >> The error affects at least the following packages: >> >> ?zeus >> >> ?obliqrt >> >> ?obliqparse >> >> ?juno-app >> >> The problem is manifested when running the stub generator (stubgen). In all >cases it reports a runtime error, attempt to reference an illegal memory locat >ion, and the file and line reference is always to line #*214* in *m3-tools\m3t >k\src\toolmisc\M3Error.m3* >> >> I suspect some recent change is the culprit. >> >> Here is an example of the error when building juno-app: >> >> C:\cm3\bin\stubgen -v1 -sno RemoteView.T -T.M3IMPTAB >> >> *** >> >> *** runtime error: >> >> *** Attempt to reference an illegal memory location. >> >> *** file "..\src\toolmisc\M3Error.m3", line 214 >> >> *** >> >> Stack trace: >> >> FP PC Procedure >> >> --------- --------- ------------------------------- >> >> 0x37f208 0xdd496c CarefulNodeLookup + 0x1e in ..\src\toolmisc\M3Error.m3 >> >> 0x37f26c 0xdd4401 RecordError + 0x2e8 in ..\src\toolmisc\M3Error.m3 >> >> 0x37f298 0xdd4026 Report + 0x23 in ..\src\toolmisc\M3Error.m3 >> >> 0x37f308 0xe46703 Eval + 0x220 in ..\src\sem\M3CExpValue.m3 >> >> 0x37f358 0xe48773 Set + 0x672 in ..\src\sem\M3CExpValue.m3 >> >> 0x37f380 0xda645b DoVisit + 0x121 in ..\src\gast\ASTWalk.m3 >> >> 0x37f3a4 0xe381de Range + 0x85 in ..\src\ast\M3AST_AS_Walk.m3 >> >> 0x37f3c8 0xda63e8 DoVisit + 0xae in ..\src\gast\ASTWalk.m3 >> >> 0x37f3ec 0xe36a81 Subrange_type + 0x85 in ..\src\ast\M3AST_AS_Walk.m3 >> >> 0x37f410 0xda63e8 DoVisit + 0xae in ..\src\gast\ASTWalk.m3 >> >> ......... ......... ... more frames ... >> >> "C:\cm3\pkg\netobj\src\netobj.tmpl", line 37: quake runtime error: exit 2147 >483647: C:\cm3\bin\stubgen -v1 -sno RemoteView.T -T.M3IMPTAB >> >> --procedure-- -line- -file--- >> >> exec -- >> >> _v_netobj 37 C:\cm3\pkg\netobj\src\netobj.tmpl >> >> netobjv1 44 C:\cm3\pkg\netobj\src\netobj.tmpl >> >> netobj 64 C:\cm3\pkg\netobj\src\netobj.tmpl >> >> include_dir 105 C:\cm3\Sandbox\m3-ui\juno-2\juno-app\src\m3makefile >> >> 4 C:\cm3\Sandbox\m3-ui\juno-2\juno-app\NT386\m3make.args >> >> Fatal Error: package build failed >> >> WARNING: Encountered an error when processing package "m3-ui\juno-2\juno-app >" for "-build". >> >> Regards, >> >> Randy Coleburn >> From rcolebur at SCIRES.COM Sun May 15 23:30:58 2011 From: rcolebur at SCIRES.COM (Coleburn, Randy) Date: Sun, 15 May 2011 17:30:58 -0400 Subject: [M3devel] [M3commit] CVS Update: cm3 In-Reply-To: <20110515210259.1804D24740E9@birch.elegosoft.com> References: <20110515210259.1804D24740E9@birch.elegosoft.com> Message-ID: Rodney: Thanks. I've confirmed that your fix seems to solve the problem. Regards, Randy Coleburn -----Original Message----- From: Rodney M. Bates [mailto:rodney at elego.de] Sent: Sunday, May 15, 2011 7:03 PM To: m3commit at elegosoft.com Subject: [M3commit] CVS Update: cm3 CVSROOT: /usr/cvs Changes by: rodney at birch. 11/05/15 23:02:58 Modified files: cm3/m3-tools/m3tk/src/fe/: M3CGo.m3 Log message: Fix a bug in m3tk that was uncovered by previous fix to LONGINT literal checking, causing NIL deref crashes. M3Go.CompileUnit was failing to call M3Error.SetCu, leaving no current unit for error messages. There are other mysteries here, but this cures the crash and reproduces previous output for at least one case. From rodney_bates at lcwb.coop Mon May 16 14:52:19 2011 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Mon, 16 May 2011 07:52:19 -0500 Subject: [M3devel] stubgen problem with m3-tools\m3tk\src\toolmisc\M3Error.m3 line 214 Message-ID: <4DD11E03.7080502@lcwb.coop> On 05/15/2011 12:23 PM, Mika Nystrom wrote: > Stupid question: > > you did "make clean" (or equivalent) first, right? > > I've noticed CM3 is pretty bad about detecting changes (at least compared > to PM3, which is my basis for all Modula-3 comparisons) and can easily > make corrupted binaries if you change things and rely on incremental > compilation---at least. if an interface has changed, which I suppose > extends to opaque information too. > > BTW, I have reviewing the LONGINT/m3tk change and Jay's -pthread change > on my todo list. CM3 just has been pushed down a bit for a while, hope > to get to them soon, not ignoring you guys. > > Looks to me like something is forgetting to call M3Error.SetCu. Not > code I've ever gone near... Yes, I just found this and checked in a fix in the head. This was a long- standing bug, but was uncovered by my recent change. There is still more to investigate here: - It looks like M3CLex.ReadNumericLiteral is not putting the 'L' into the literal. - It looks like M3CLex.ReadHexDigits won't recognize the 'L' at all, for a based literal. - It looks like somewhere even "0" is getting typed as Longint_literal. As I remember, later processing of LONGINT literals will tolerate the trailing 'L'. > > Mika > > "Rodney M. Bates" writes: >> Hmm, I checked in a change to the head on 2011-4-26 that could lie right on >> this backtrace. It is in M3CExpValue.Eval, and contains a call on M3Error.Rep >> ort. >> There are several other calls in M3CExpValue.Eval to M3Error.Report, not invol >> ving >> my change. Simple proportioning between hex displacements and source line cou >> nts >> suggests it is the call in the change. >> >> But it is hard to image how my change could do anything but reduce the set of >> cases where this call is executed, and any such cases remaining sould have bee >> n >> with the same values of all variables, compared to before. >> >> Moreover, this or any of the calls in Eval on Report would have been producing >> error messages before the change. I presume there were no such error messages >> formerly? >> >> Are there any LONGINT literals in the code stubgen is being run on? The chang >> e >> only weakens an overzealous error check for them. >> >> On 05/14/2011 10:57 PM, Coleburn, Randy wrote: >>> I am seeing a new error when building on Windows 2000, XP, and 7. >>> >>> The error affects at least the following packages: >>> >>> ?zeus >>> >>> ?obliqrt >>> >>> ?obliqparse >>> >>> ?juno-app >>> >>> The problem is manifested when running the stub generator (stubgen). In all >> cases it reports a runtime error, attempt to reference an illegal memory locat >> ion, and the file and line reference is always to line #*214* in *m3-tools\m3t >> k\src\toolmisc\M3Error.m3* >>> >>> I suspect some recent change is the culprit. >>> >>> Here is an example of the error when building juno-app: >>> >>> C:\cm3\bin\stubgen -v1 -sno RemoteView.T -T.M3IMPTAB >>> >>> *** >>> >>> *** runtime error: >>> >>> *** Attempt to reference an illegal memory location. >>> >>> *** file "..\src\toolmisc\M3Error.m3", line 214 >>> >>> *** >>> >>> Stack trace: >>> >>> FP PC Procedure >>> >>> --------- --------- ------------------------------- >>> >>> 0x37f208 0xdd496c CarefulNodeLookup + 0x1e in ..\src\toolmisc\M3Error.m3 >>> >>> 0x37f26c 0xdd4401 RecordError + 0x2e8 in ..\src\toolmisc\M3Error.m3 >>> >>> 0x37f298 0xdd4026 Report + 0x23 in ..\src\toolmisc\M3Error.m3 >>> >>> 0x37f308 0xe46703 Eval + 0x220 in ..\src\sem\M3CExpValue.m3 >>> >>> 0x37f358 0xe48773 Set + 0x672 in ..\src\sem\M3CExpValue.m3 >>> >>> 0x37f380 0xda645b DoVisit + 0x121 in ..\src\gast\ASTWalk.m3 >>> >>> 0x37f3a4 0xe381de Range + 0x85 in ..\src\ast\M3AST_AS_Walk.m3 >>> >>> 0x37f3c8 0xda63e8 DoVisit + 0xae in ..\src\gast\ASTWalk.m3 >>> >>> 0x37f3ec 0xe36a81 Subrange_type + 0x85 in ..\src\ast\M3AST_AS_Walk.m3 >>> >>> 0x37f410 0xda63e8 DoVisit + 0xae in ..\src\gast\ASTWalk.m3 >>> >>> ......... ......... ... more frames ... >>> >>> "C:\cm3\pkg\netobj\src\netobj.tmpl", line 37: quake runtime error: exit 2147 >> 483647: C:\cm3\bin\stubgen -v1 -sno RemoteView.T -T.M3IMPTAB >>> >>> --procedure-- -line- -file--- >>> >>> exec -- >>> >>> _v_netobj 37 C:\cm3\pkg\netobj\src\netobj.tmpl >>> >>> netobjv1 44 C:\cm3\pkg\netobj\src\netobj.tmpl >>> >>> netobj 64 C:\cm3\pkg\netobj\src\netobj.tmpl >>> >>> include_dir 105 C:\cm3\Sandbox\m3-ui\juno-2\juno-app\src\m3makefile >>> >>> 4 C:\cm3\Sandbox\m3-ui\juno-2\juno-app\NT386\m3make.args >>> >>> Fatal Error: package build failed >>> >>> WARNING: Encountered an error when processing package "m3-ui\juno-2\juno-app >> " for "-build". >>> >>> Regards, >>> >>> Randy Coleburn >>> From rodney_bates at lcwb.coop Tue May 17 23:47:08 2011 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Tue, 17 May 2011 16:47:08 -0500 Subject: [M3devel] LONGINT -> more bugs in m3tk In-Reply-To: <4DB6F2B2.3090905@lcwb.coop> References: <20110419115106.7E6A31A207A@async.async.caltech.edu> <4DB6F2B2.3090905@lcwb.coop> Message-ID: <4DD2ECDC.8070806@lcwb.coop> Mika, can you tell me what main program and command you used to get these errors? It would help me to test changes to m3tk. On 04/26/2011 11:28 AM, Rodney M. Bates wrote: > I just checked in a patch tp M3CExpValue.m3 in m3tk, in the head, which I believe will fix this > bug. I compiled it, but have not tested it, as I am sure Mika has this case to retry > more quickly than I can. > > On 04/19/2011 06:51 AM, Mika Nystrom wrote: >> Hello m3devel, >> >> If anyone knows how to fix the following trivially, please go ahead. >> >> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,45: type error in arguments to binary operator >> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,25: bad numeric literal >> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,51: bad numeric literal >> >> (errors reported by m3tk). >> >> The offending line is: >> >> INTERFACE BasicCtypes; >> >> IMPORT Word, Long; >> >> TYPE >> (* the four signed integer types *) >> signed_char = [-16_7f-1 .. 16_7f]; >> short_int = [-16_7fff-1 .. 16_7fff]; >> int = [-16_7fffffff-1 .. 16_7fffffff]; >> long_int = [-16_7fffffffffffffff -1 .. 16_7fffffffffffffff ]; >> long_long = [-16_7fffffffffffffffL-1L .. 16_7fffffffffffffffL]; (** HERE **) >> >> (* the four unsigned integer types *) >> unsigned_char = [16_0 .. 16_ff]; >> unsigned_short_int = [16_0 .. 16_ffff]; >> unsigned_int = [16_0 .. 16_ffffffff]; >> unsigned_long_int = Word.T; >> unsigned_long_long = Long.T; >> >> (* the three floating types *) >> float = REAL; >> double = LONGREAL; >> long_double = EXTENDED; >> >> (* char *) >> char = signed_char; >> >> END BasicCtypes. >> >> I'll look at it myself, but not immediately (no time). Workaround for now. >> >> Mika >> > From mika at async.caltech.edu Wed May 18 03:35:42 2011 From: mika at async.caltech.edu (Mika Nystrom) Date: Tue, 17 May 2011 18:35:42 -0700 Subject: [M3devel] LONGINT -> more bugs in m3tk In-Reply-To: <4DD2ECDC.8070806@lcwb.coop> References: <20110419115106.7E6A31A207A@async.async.caltech.edu> <4DB6F2B2.3090905@lcwb.coop> <4DD2ECDC.8070806@lcwb.coop> Message-ID: <20110518013542.194111A2078@async.async.caltech.edu> I think you'll get that error if you run stubgen on anything that references a type from BasicCtypes (e.g., int, char_star ...) I'm pretty sure I actually got it running the stub generator for my Scheme interpreter, which I have posted links to here a few times, but I haven't had time to push into CM3 yet. Mika "Rodney M. Bates" writes: >Mika, can you tell me what main program and command you used to get these erro >rs? >It would help me to test changes to m3tk. > >On 04/26/2011 11:28 AM, Rodney M. Bates wrote: >> I just checked in a patch tp M3CExpValue.m3 in m3tk, in the head, which I be >lieve will fix this >> bug. I compiled it, but have not tested it, as I am sure Mika has this case >to retry >> more quickly than I can. >> >> On 04/19/2011 06:51 AM, Mika Nystrom wrote: >>> Hello m3devel, >>> >>> If anyone knows how to fix the following trivially, please go ahead. >>> >>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,45: type e >rror in arguments to binary operator >>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,25: bad nu >meric literal >>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,51: bad nu >meric literal >>> >>> (errors reported by m3tk). >>> >>> The offending line is: >>> >>> INTERFACE BasicCtypes; >>> >>> IMPORT Word, Long; >>> >>> TYPE >>> (* the four signed integer types *) >>> signed_char = [-16_7f-1 .. 16_7f]; >>> short_int = [-16_7fff-1 .. 16_7fff]; >>> int = [-16_7fffffff-1 .. 16_7fffffff]; >>> long_int = [-16_7fffffffffffffff -1 .. 16_7fffffffffffffff ]; >>> long_long = [-16_7fffffffffffffffL-1L .. 16_7fffffffffffffffL]; (** HERE ** >) >>> >>> (* the four unsigned integer types *) >>> unsigned_char = [16_0 .. 16_ff]; >>> unsigned_short_int = [16_0 .. 16_ffff]; >>> unsigned_int = [16_0 .. 16_ffffffff]; >>> unsigned_long_int = Word.T; >>> unsigned_long_long = Long.T; >>> >>> (* the three floating types *) >>> float = REAL; >>> double = LONGREAL; >>> long_double = EXTENDED; >>> >>> (* char *) >>> char = signed_char; >>> >>> END BasicCtypes. >>> >>> I'll look at it myself, but not immediately (no time). Workaround for now. >>> >>> Mika >>> >> From rcolebur at SCIRES.COM Wed May 18 20:27:44 2011 From: rcolebur at SCIRES.COM (Coleburn, Randy) Date: Wed, 18 May 2011 14:27:44 -0400 Subject: [M3devel] LONGINT -> more bugs in m3tk In-Reply-To: <20110518013542.194111A2078@async.async.caltech.edu> References: <20110419115106.7E6A31A207A@async.async.caltech.edu> <4DB6F2B2.3090905@lcwb.coop> <4DD2ECDC.8070806@lcwb.coop> <20110518013542.194111A2078@async.async.caltech.edu> Message-ID: While we are on the subject of the stub generator, there is another long-standing problem. I've submitted this one years ago and I think I still have the example program I devised to show it. So, I'll try to dig this up and put it into the bug tracker. The basic situation is that there are cases where the stub generator doesn't generate imports for all interfaces needed by the resulting stub. You can work around this problem by manually editing the generated stub to provide the missing imports, but this gets old quickly. I'll send a follow-up post with the details once I find them in my archives. Regards, Randy Coleburn -----Original Message----- From: Mika Nystrom [mailto:mika at async.caltech.edu] Sent: Tuesday, May 17, 2011 9:36 PM To: Rodney M. Bates Cc: m3devel at elegosoft.com Subject: Re: [M3devel] LONGINT -> more bugs in m3tk I think you'll get that error if you run stubgen on anything that references a type from BasicCtypes (e.g., int, char_star ...) I'm pretty sure I actually got it running the stub generator for my Scheme interpreter, which I have posted links to here a few times, but I haven't had time to push into CM3 yet. Mika "Rodney M. Bates" writes: >Mika, can you tell me what main program and command you used to get these erro >rs? >It would help me to test changes to m3tk. > >On 04/26/2011 11:28 AM, Rodney M. Bates wrote: >> I just checked in a patch tp M3CExpValue.m3 in m3tk, in the head, which I be >lieve will fix this >> bug. I compiled it, but have not tested it, as I am sure Mika has this case >to retry >> more quickly than I can. >> >> On 04/19/2011 06:51 AM, Mika Nystrom wrote: >>> Hello m3devel, >>> >>> If anyone knows how to fix the following trivially, please go ahead. >>> >>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,45: type e >rror in arguments to binary operator >>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,25: bad nu >meric literal >>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,51: bad nu >meric literal >>> >>> (errors reported by m3tk). >>> >>> The offending line is: >>> >>> INTERFACE BasicCtypes; >>> >>> IMPORT Word, Long; >>> >>> TYPE >>> (* the four signed integer types *) >>> signed_char = [-16_7f-1 .. 16_7f]; >>> short_int = [-16_7fff-1 .. 16_7fff]; >>> int = [-16_7fffffff-1 .. 16_7fffffff]; >>> long_int = [-16_7fffffffffffffff -1 .. 16_7fffffffffffffff ]; >>> long_long = [-16_7fffffffffffffffL-1L .. 16_7fffffffffffffffL]; (** HERE ** >) >>> >>> (* the four unsigned integer types *) >>> unsigned_char = [16_0 .. 16_ff]; >>> unsigned_short_int = [16_0 .. 16_ffff]; >>> unsigned_int = [16_0 .. 16_ffffffff]; >>> unsigned_long_int = Word.T; >>> unsigned_long_long = Long.T; >>> >>> (* the three floating types *) >>> float = REAL; >>> double = LONGREAL; >>> long_double = EXTENDED; >>> >>> (* char *) >>> char = signed_char; >>> >>> END BasicCtypes. >>> >>> I'll look at it myself, but not immediately (no time). Workaround for now. >>> >>> Mika >>> >> From rcolebur at SCIRES.COM Wed May 18 23:04:41 2011 From: rcolebur at SCIRES.COM (Coleburn, Randy) Date: Wed, 18 May 2011 17:04:41 -0400 Subject: [M3devel] LONGINT -> more bugs in m3tk In-Reply-To: References: <20110419115106.7E6A31A207A@async.async.caltech.edu> <4DB6F2B2.3090905@lcwb.coop> <4DD2ECDC.8070806@lcwb.coop> <20110518013542.194111A2078@async.async.caltech.edu> Message-ID: Ok, I found some stuff in my archives about a set of documented stubgen problems, but this stuff doesn't include the problem I described with the failure to generate imports for all interfaces. Actually, I think this interface import problem is with the network objects stub generator, so I will either find or create an example of this problem and submit later. Here is a short program (with comments) that demonstrates some stubgen problems. I generated this program back in January 2001, so these are long-standing issues. Regards, Randy Coleburn m3makefile is: import("libm3") import("netobj") Interface("StubGenProblem") Netobj("StubGenProblem", "T") Library("NetObjProblem") StubGenProblem.i3 is: INTERFACE StubGenProblem; (* Interface demonstrating problem with Network Objects Stub Generator *) (* R.C.Coleburn, 01/24/2001 *) IMPORT NetObj, Thread; TYPE MyRecord = RECORD a: INTEGER := 0; b: TEXT := "zero"; END; CONST Default = MyRecord{1, "one"}; TYPE MyObject = OBJECT myRec: MyRecord := Default; (* if you change above line to be: myRec: MyRecord; that is, leave out the default initializer, the stub generator no longer complains when parameters of type MyObject are passed to methods of type T. *) END; TYPE T = NetObj.T OBJECT METHODS (* method testA is accepted by the NetObj Stub Generator *) testA(myRec: MyRecord) RAISES {NetObj.Error, Thread.Alerted}; (* method testB is accepted by the NetObj Stub Generator *) testB(myRec: MyRecord := Default) RAISES {NetObj.Error, Thread.Alerted}; (* method testC yeilds the following error from the NetObj Stub Generator: stubgen: INTERNAL ERROR: AstToVal.ProcessExp: unsupported value *) (* Does anyone know why the stub generator can't handle this? *) (* Does anyone know of a workaround or a fix to the stub generator? *) testC(myObj: MyObject) RAISES {NetObj.Error, Thread.Alerted}; (* BTW, if you comment out the assignment of Default to MyObject.myRec in the declaration on line 16, the stub generator no longer complains. So, it seems that the problem is passing an object parameter containing a record field member with a default initializer. Note that passing a record parameter with a default initializer is not a problem for the stub generator. *) END; END StubGenProblem. -----Original Message----- From: Coleburn, Randy Sent: Wednesday, May 18, 2011 2:28 PM To: Mika Nystrom; Rodney M. Bates Cc: m3devel at elegosoft.com Subject: Re: [M3devel] LONGINT -> more bugs in m3tk While we are on the subject of the stub generator, there is another long-standing problem. I've submitted this one years ago and I think I still have the example program I devised to show it. So, I'll try to dig this up and put it into the bug tracker. The basic situation is that there are cases where the stub generator doesn't generate imports for all interfaces needed by the resulting stub. You can work around this problem by manually editing the generated stub to provide the missing imports, but this gets old quickly. I'll send a follow-up post with the details once I find them in my archives. Regards, Randy Coleburn From dabenavidesd at yahoo.es Wed May 18 23:49:05 2011 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Wed, 18 May 2011 22:49:05 +0100 (BST) Subject: [M3devel] LONGINT -> more bugs in m3tk In-Reply-To: Message-ID: <846840.19495.qm@web29712.mail.ird.yahoo.com> Hi all: This is good news (though old) shows up, this is perhaps the problem with Obliq problem (worked in pm3), by the way what could be missing if so from there in CM3? Thanks in advance PS It might be that CM3 once worked Obliq, since there is a thesis reportedly working on Obliq3D of Blair MacIntyre, an augmented reality system, this is probably 1999, so a lot of stuff might came or not after that. --- El mi?, 18/5/11, Coleburn, Randy escribi?: > De: Coleburn, Randy > Asunto: Re: [M3devel] LONGINT -> more bugs in m3tk > Para: "m3devel at elegosoft.com" > Fecha: mi?rcoles, 18 de mayo, 2011 16:04 > Ok, I found some stuff in my archives > about a set of documented stubgen problems, but this stuff > doesn't include the problem I described with the failure to > generate imports for all interfaces. Actually, I think > this interface import problem is with the network objects > stub generator, so I will either find or create an example > of this problem and submit later. > > Here is a short program (with comments) that demonstrates > some stubgen problems. I generated this program back > in January 2001, so these are long-standing issues. > > Regards, > Randy Coleburn > > > m3makefile is: > > import("libm3") > import("netobj") > Interface("StubGenProblem") > Netobj("StubGenProblem", "T") > Library("NetObjProblem") > > > > StubGenProblem.i3 is: > > INTERFACE StubGenProblem; > (* Interface demonstrating problem with Network Objects > Stub Generator *) > (* R.C.Coleburn, 01/24/2001 *) > IMPORT > NetObj, > Thread; > TYPE > MyRecord = RECORD > a: INTEGER := 0; > b: TEXT := "zero"; > END; > CONST > Default = MyRecord{1, "one"}; > TYPE > MyObject = OBJECT > myRec: MyRecord := Default; > (* if you change above line to be: > myRec: MyRecord; > that is, leave out > the default initializer, the stub > generator no longer > complains when parameters of type > MyObject are passed > to methods of type T. *) > END; > TYPE > T = NetObj.T OBJECT > METHODS > (* method testA is accepted by the > NetObj Stub Generator *) > testA(myRec: MyRecord) RAISES > {NetObj.Error, Thread.Alerted}; > > (* method testB is accepted by the > NetObj Stub Generator *) > testB(myRec: MyRecord := Default) > RAISES {NetObj.Error, Thread.Alerted}; > > (* method testC yeilds the following > error from the NetObj Stub Generator: > stubgen: INTERNAL > ERROR: AstToVal.ProcessExp: unsupported value *) > (* Does anyone know why the stub > generator can't handle this? *) > (* Does anyone know of a workaround or > a fix to the stub generator? *) > testC(myObj: MyObject) RAISES > {NetObj.Error, Thread.Alerted}; > > (* BTW, if you comment out the > assignment of Default to MyObject.myRec > in the declaration on line 16, the > stub generator no longer complains. > So, it seems that the problem is > passing an object parameter containing > a record field member with a default > initializer. Note that passing a > record parameter with a default > initializer is not a problem for the > stub generator. *) > END; > END StubGenProblem. > > > > -----Original Message----- > From: Coleburn, Randy > Sent: Wednesday, May 18, 2011 2:28 PM > To: Mika Nystrom; Rodney M. Bates > Cc: m3devel at elegosoft.com > Subject: Re: [M3devel] LONGINT -> more bugs in m3tk > > While we are on the subject of the stub generator, there is > another long-standing problem. > > I've submitted this one years ago and I think I still have > the example program I devised to show it. > > So, I'll try to dig this up and put it into the bug > tracker. > > The basic situation is that there are cases where the stub > generator doesn't generate imports for all interfaces needed > by the resulting stub. You can work around this > problem by manually editing the generated stub to provide > the missing imports, but this gets old quickly. > > I'll send a follow-up post with the details once I find > them in my archives. > > Regards, > Randy Coleburn > From mika at async.caltech.edu Thu May 19 01:38:58 2011 From: mika at async.caltech.edu (Mika Nystrom) Date: Wed, 18 May 2011 16:38:58 -0700 Subject: [M3devel] LONGINT -> more bugs in m3tk In-Reply-To: References: <20110419115106.7E6A31A207A@async.async.caltech.edu> <4DB6F2B2.3090905@lcwb.coop> <4DD2ECDC.8070806@lcwb.coop> <20110518013542.194111A2078@async.async.caltech.edu> Message-ID: <20110518233858.545FB1A2078@async.async.caltech.edu> Ah, ok... such bugs ought to be fairly easy to fix. Maybe... To be clear, there are at least three stub generators that use m3tk that I know of (and probably others too) "stubgen" for Network Objects "stablegen" for some sort of stable storage database "sstubgen" (not in CM3 yet!) that generates stubs for the "Modula-Scheme system" (what I referenced below) Mika "Coleburn, Randy" writes: >While we are on the subject of the stub generator, there is another long-st= >anding problem. > >I've submitted this one years ago and I think I still have the example prog= >ram I devised to show it. > >So, I'll try to dig this up and put it into the bug tracker. > >The basic situation is that there are cases where the stub generator doesn'= >t generate imports for all interfaces needed by the resulting stub. You ca= >n work around this problem by manually editing the generated stub to provid= >e the missing imports, but this gets old quickly. > >I'll send a follow-up post with the details once I find them in my archives= >. > >Regards, >Randy Coleburn > >-----Original Message----- >From: Mika Nystrom [mailto:mika at async.caltech.edu]=20 >Sent: Tuesday, May 17, 2011 9:36 PM >To: Rodney M. Bates >Cc: m3devel at elegosoft.com >Subject: Re: [M3devel] LONGINT -> more bugs in m3tk > >I think you'll get that error if you run stubgen on anything that reference= >s >a type from BasicCtypes (e.g., int, char_star ...) > >I'm pretty sure I actually got it running the stub generator for my >Scheme interpreter, which I have posted links to here a few times, but I >haven't had time to push into CM3 yet. > > Mika > >"Rodney M. Bates" writes: >>Mika, can you tell me what main program and command you used to get these = >erro >>rs? >>It would help me to test changes to m3tk. >> >>On 04/26/2011 11:28 AM, Rodney M. Bates wrote: >>> I just checked in a patch tp M3CExpValue.m3 in m3tk, in the head, which = >I be >>lieve will fix this >>> bug. I compiled it, but have not tested it, as I am sure Mika has this c= >ase=20 >>to retry >>> more quickly than I can. >>> >>> On 04/19/2011 06:51 AM, Mika Nystrom wrote: >>>> Hello m3devel, >>>> >>>> If anyone knows how to fix the following trivially, please go ahead. >>>> >>>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,45: ty= >pe e >>rror in arguments to binary operator >>>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,25: ba= >d nu >>meric literal >>>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,51: ba= >d nu >>meric literal >>>> >>>> (errors reported by m3tk). >>>> >>>> The offending line is: >>>> >>>> INTERFACE BasicCtypes; >>>> >>>> IMPORT Word, Long; >>>> >>>> TYPE >>>> (* the four signed integer types *) >>>> signed_char =3D [-16_7f-1 .. 16_7f]; >>>> short_int =3D [-16_7fff-1 .. 16_7fff]; >>>> int =3D [-16_7fffffff-1 .. 16_7fffffff]; >>>> long_int =3D [-16_7fffffffffffffff -1 .. 16_7fffffffffffffff ]; >>>> long_long =3D [-16_7fffffffffffffffL-1L .. 16_7fffffffffffffffL]; (** H= >ERE ** >>) >>>> >>>> (* the four unsigned integer types *) >>>> unsigned_char =3D [16_0 .. 16_ff]; >>>> unsigned_short_int =3D [16_0 .. 16_ffff]; >>>> unsigned_int =3D [16_0 .. 16_ffffffff]; >>>> unsigned_long_int =3D Word.T; >>>> unsigned_long_long =3D Long.T; >>>> >>>> (* the three floating types *) >>>> float =3D REAL; >>>> double =3D LONGREAL; >>>> long_double =3D EXTENDED; >>>> >>>> (* char *) >>>> char =3D signed_char; >>>> >>>> END BasicCtypes. >>>> >>>> I'll look at it myself, but not immediately (no time). Workaround for n= >ow. >>>> >>>> Mika >>>> >>> From rodney_bates at lcwb.coop Wed May 18 23:41:31 2011 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Wed, 18 May 2011 16:41:31 -0500 Subject: [M3devel] LONGINT -> more bugs in m3tk In-Reply-To: <20110518013542.194111A2078@async.async.caltech.edu> References: <20110419115106.7E6A31A207A@async.async.caltech.edu> <4DB6F2B2.3090905@lcwb.coop> <4DD2ECDC.8070806@lcwb.coop> <20110518013542.194111A2078@async.async.caltech.edu> Message-ID: <4DD43D0B.6080400@lcwb.coop> Thanks. That got me going. On 05/17/2011 08:35 PM, Mika Nystrom wrote: > I think you'll get that error if you run stubgen on anything that references > a type from BasicCtypes (e.g., int, char_star ...) > > I'm pretty sure I actually got it running the stub generator for my > Scheme interpreter, which I have posted links to here a few times, but I > haven't had time to push into CM3 yet. > > Mika > > "Rodney M. Bates" writes: >> Mika, can you tell me what main program and command you used to get these erro >> rs? >> It would help me to test changes to m3tk. >> >> On 04/26/2011 11:28 AM, Rodney M. Bates wrote: >>> I just checked in a patch tp M3CExpValue.m3 in m3tk, in the head, which I be >> lieve will fix this >>> bug. I compiled it, but have not tested it, as I am sure Mika has this case >> to retry >>> more quickly than I can. >>> >>> On 04/19/2011 06:51 AM, Mika Nystrom wrote: >>>> Hello m3devel, >>>> >>>> If anyone knows how to fix the following trivially, please go ahead. >>>> >>>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,45: type e >> rror in arguments to binary operator >>>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,25: bad nu >> meric literal >>>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,51: bad nu >> meric literal >>>> >>>> (errors reported by m3tk). >>>> >>>> The offending line is: >>>> >>>> INTERFACE BasicCtypes; >>>> >>>> IMPORT Word, Long; >>>> >>>> TYPE >>>> (* the four signed integer types *) >>>> signed_char = [-16_7f-1 .. 16_7f]; >>>> short_int = [-16_7fff-1 .. 16_7fff]; >>>> int = [-16_7fffffff-1 .. 16_7fffffff]; >>>> long_int = [-16_7fffffffffffffff -1 .. 16_7fffffffffffffff ]; >>>> long_long = [-16_7fffffffffffffffL-1L .. 16_7fffffffffffffffL]; (** HERE ** >> ) >>>> >>>> (* the four unsigned integer types *) >>>> unsigned_char = [16_0 .. 16_ff]; >>>> unsigned_short_int = [16_0 .. 16_ffff]; >>>> unsigned_int = [16_0 .. 16_ffffffff]; >>>> unsigned_long_int = Word.T; >>>> unsigned_long_long = Long.T; >>>> >>>> (* the three floating types *) >>>> float = REAL; >>>> double = LONGREAL; >>>> long_double = EXTENDED; >>>> >>>> (* char *) >>>> char = signed_char; >>>> >>>> END BasicCtypes. >>>> >>>> I'll look at it myself, but not immediately (no time). Workaround for now. >>>> >>>> Mika >>>> >>> > From rodney_bates at lcwb.coop Thu May 19 17:41:15 2011 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Thu, 19 May 2011 10:41:15 -0500 Subject: [M3devel] missing libm3/src/types Message-ID: <4DD53A1B.3030805@lcwb.coop> What happened to cm3/m3-libs/libm3/src/types and its contents in the head? They all are gone, but cm3/m3-libs/libm3/src/m3makefile contains include_dir ("types"), and libm3 won't build: rodney at allegheny:~/proj/m3/cm3-new/cm3/scripts$ ./do-pkg.sh build libm3 /home/rodney/proj/m3/cm3-new/cm3/scripts/pkgmap.sh -c "cm3 -build -override $RARGS -DROOT='/home/rodney/proj/m3/cm3-new/cm3' " libm3 === package /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3 === +++ cm3 -build -override $RARGS -DROOT='/home/rodney/proj/m3/cm3-new/cm3' +++ --- building in AMD64_LINUX --- "/home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/m3makefile", line 27: quake runtime error: unable to open "/home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/types/m3makefile" for reading --procedure-- -line- -file--- include_dir -- include_dir 27 /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/m3makefile 6 /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/AMD64_LINUX/m3make.args Fatal Error: package build failed ==> /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3 done rodney at allegheny:~/proj/m3/cm3-new/cm3/scripts$ It looks like either types needs to come back, or include_dir ("types") needs to go away, but which? If somebody knows, it would save a lot of time poking around. From hosking at cs.purdue.edu Thu May 19 17:45:59 2011 From: hosking at cs.purdue.edu (Tony Hosking) Date: Thu, 19 May 2011 11:45:59 -0400 Subject: [M3devel] missing libm3/src/types In-Reply-To: <4DD53A1B.3030805@lcwb.coop> References: <4DD53A1B.3030805@lcwb.coop> Message-ID: <3169D748-68A3-4A9A-A582-60C68D32AB94@cs.purdue.edu> Moved to m3core. There shouldn't be anything in libm3/types. On May 19, 2011, at 11:41 AM, Rodney M. Bates wrote: > What happened to cm3/m3-libs/libm3/src/types and its contents in the head? > They all are gone, but cm3/m3-libs/libm3/src/m3makefile contains > include_dir ("types"), and libm3 won't build: > > > rodney at allegheny:~/proj/m3/cm3-new/cm3/scripts$ ./do-pkg.sh build libm3 > /home/rodney/proj/m3/cm3-new/cm3/scripts/pkgmap.sh -c "cm3 -build -override $RARGS -DROOT='/home/rodney/proj/m3/cm3-new/cm3' " libm3 > === package /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3 === > +++ cm3 -build -override $RARGS -DROOT='/home/rodney/proj/m3/cm3-new/cm3' +++ > --- building in AMD64_LINUX --- > > "/home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/m3makefile", line 27: quake runtime error: unable to open "/home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/types/m3makefile" for reading > > --procedure-- -line- -file--- > include_dir -- > include_dir 27 /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/m3makefile > 6 /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/AMD64_LINUX/m3make.args > > Fatal Error: package build failed > ==> /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3 done > > rodney at allegheny:~/proj/m3/cm3-new/cm3/scripts$ > > It looks like either types needs to come back, or include_dir ("types") needs to go away, > but which? If somebody knows, it would save a lot of time poking around. From hosking at cs.purdue.edu Thu May 19 17:51:36 2011 From: hosking at cs.purdue.edu (Tony Hosking) Date: Thu, 19 May 2011 11:51:36 -0400 Subject: [M3devel] missing libm3/src/types In-Reply-To: <3169D748-68A3-4A9A-A582-60C68D32AB94@cs.purdue.edu> References: <4DD53A1B.3030805@lcwb.coop> <3169D748-68A3-4A9A-A582-60C68D32AB94@cs.purdue.edu> Message-ID: <55EDF7AD-B04C-48DF-9266-7A3B3A61CDCF@cs.purdue.edu> Actually, looks like Jay tried to restore LongrealType and RealType for Mika. Clients should really be adjusted to include: IMPORT LongFloat as LongrealType, RealFloat as RealType; On May 19, 2011, at 11:45 AM, Tony Hosking wrote: > Moved to m3core. There shouldn't be anything in libm3/types. > > On May 19, 2011, at 11:41 AM, Rodney M. Bates wrote: > >> What happened to cm3/m3-libs/libm3/src/types and its contents in the head? >> They all are gone, but cm3/m3-libs/libm3/src/m3makefile contains >> include_dir ("types"), and libm3 won't build: >> >> >> rodney at allegheny:~/proj/m3/cm3-new/cm3/scripts$ ./do-pkg.sh build libm3 >> /home/rodney/proj/m3/cm3-new/cm3/scripts/pkgmap.sh -c "cm3 -build -override $RARGS -DROOT='/home/rodney/proj/m3/cm3-new/cm3' " libm3 >> === package /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3 === >> +++ cm3 -build -override $RARGS -DROOT='/home/rodney/proj/m3/cm3-new/cm3' +++ >> --- building in AMD64_LINUX --- >> >> "/home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/m3makefile", line 27: quake runtime error: unable to open "/home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/types/m3makefile" for reading >> >> --procedure-- -line- -file--- >> include_dir -- >> include_dir 27 /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/m3makefile >> 6 /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/AMD64_LINUX/m3make.args >> >> Fatal Error: package build failed >> ==> /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3 done >> >> rodney at allegheny:~/proj/m3/cm3-new/cm3/scripts$ >> >> It looks like either types needs to come back, or include_dir ("types") needs to go away, >> but which? If somebody knows, it would save a lot of time poking around. > From dabenavidesd at yahoo.es Thu May 19 18:18:20 2011 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Thu, 19 May 2011 17:18:20 +0100 (BST) Subject: [M3devel] missing libm3/src/types In-Reply-To: <3169D748-68A3-4A9A-A582-60C68D32AB94@cs.purdue.edu> Message-ID: <321796.84407.qm@web29715.mail.ird.yahoo.com> Hi all: if it could affect the compiler usage if in fact such usage why would one give such types inside cm3 or m3build process aside of m3core, I mean the top hierarchy must be primitive types at bottom then refs, objects, etc or reverse, and its type rules besides modules and interfaces, perhaps a good example would be to see the interfaces of Modula-2+ Vulcan system, since it had everything compiled cached and managed to survive even crashes and bridge everything to the Vesta CM system, quick large compilations, see: http://www-cs-faculty.stanford.edu/~eroberts/cv.html An advanced system to type check may require quick timely access to large nodes since type inference is something very dependent on its size, a bigger tree a bigger problem, even if ever get to compile type inferencing (an Obliq prototype already done), but many modules around would be like dancing in hard feet over sized. Thanks in advance --- El jue, 19/5/11, Tony Hosking escribi?: > De: Tony Hosking > Asunto: Re: [M3devel] missing libm3/src/types > Para: "Rodney M. Bates" > CC: "m3devel" > Fecha: jueves, 19 de mayo, 2011 10:45 > Moved to m3core. There > shouldn't be anything in libm3/types. > > On May 19, 2011, at 11:41 AM, Rodney M. Bates wrote: > > > What happened to cm3/m3-libs/libm3/src/types and its > contents in the head? > > They all are gone, but > cm3/m3-libs/libm3/src/m3makefile contains > > include_dir ("types"), and libm3 won't build: > > > > > > rodney at allegheny:~/proj/m3/cm3-new/cm3/scripts$ > ./do-pkg.sh build libm3 > > /home/rodney/proj/m3/cm3-new/cm3/scripts/pkgmap.sh -c > "cm3 -build -override $RARGS > -DROOT='/home/rodney/proj/m3/cm3-new/cm3' " libm3 > > === package > /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3 === > > +++ cm3 -build -override $RARGS > -DROOT='/home/rodney/proj/m3/cm3-new/cm3' +++ > > --- building in AMD64_LINUX --- > > > > > "/home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/m3makefile", > line 27: quake runtime error: unable to open > "/home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/types/m3makefile" > for reading > > > > --procedure-- -line- -file--- > > include_dir -- > > > include_dir 27 > /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/m3makefile > > > 6 > /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/AMD64_LINUX/m3make.args > > > > Fatal Error: package build failed > > ==> /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3 > done > > > > rodney at allegheny:~/proj/m3/cm3-new/cm3/scripts$ > > > > It looks like either types needs to come back, or > include_dir ("types") needs to go away, > > but which? If somebody knows, it would save a > lot of time poking around. > > From jay.krell at cornell.edu Sun May 22 10:26:30 2011 From: jay.krell at cornell.edu (Jay K) Date: Sun, 22 May 2011 08:26:30 +0000 Subject: [M3devel] range analysis? Message-ID: I've been sitting on this diff a long while. In some places the frontend knows the bounds of a type/value and will optimize away range checks. I'm pretty sure. This makes it do that more. I haven't looked at or tested this in ages. But the basic idea seems sound, simple, easy enough to get a few small wins from. For example if you have: a: [-10..-1]; b: [1..10]; then all comparisons between a and b are compile-time constant. Comparisons of cardinals to negative numbers, likewise. One thing maybe missing below is handling of empty ranges like a: [1..-1]; The code assumes the minimum of a type is less than or equal to its maximum. Index: m3-sys/m3front/src/misc/CG.i3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.i3,v retrieving revision 1.15 diff -r1.15 CG.i3 11c11 < IMPORT Target, M3CG, M3; --- > IMPORT Target, M3CG, M3, TInt; 402c402,406 < PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type); --- > PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type; > min_valid: BOOLEAN := FALSE; > max_valid: BOOLEAN := FALSE; > min: Target.Int := TInt.Zero; > max: Target.Int := TInt.Zero); 414,415c418,423 < PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0); < (* == Load (v, o, t.size, t.align, t) *) --- > PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0; > min_valid: BOOLEAN := FALSE; > max_valid: BOOLEAN := FALSE; > min: Target.Int := TInt.Zero; > max: Target.Int := TInt.Zero); > (* == Load (v, o, t.size, t.align, t, min/max...) *) Index: m3-sys/m3front/src/misc/CG.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.m3,v retrieving revision 1.40 diff -r1.40 CG.m3 13c13 < IMPORT M3, M3CG, M3CG_Ops, M3CG_Check; --- > IMPORT M3, M3CG, M3CG_Ops, M3CG_Check, RTIO, RTParams; 45a46,49 > min_valid : BOOLEAN := FALSE; (* whether or not min is valid *) > max_valid : BOOLEAN := FALSE; (* whether or not max is valid *) > min : Target.Int := TInt.Zero; (* the minimum possible value *) > max : Target.Int := TInt.Zero; (* the maximum possible value *) 80c84,85 < VAR --- > VAR > debug := FALSE; 604a610,614 > v.min := TInt.Zero; > v.max := TInt.Zero; > v.min_valid := FALSE; > v.max_valid := FALSE; > 766a777,780 > x.min := TInt.Zero; > x.max := TInt.Zero; > x.min_valid := FALSE; > x.max_valid := FALSE; 978a993,995 > IF debug THEN > RTIO.PutText("m3front:cg:Init_int:NOT in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); > END; 980a998,1001 > END; > > IF debug THEN > RTIO.PutText("m3front:cg:Init_int:in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); 1266c1287,1291 < PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type) = --- > PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type; > min_valid: BOOLEAN := FALSE; > max_valid: BOOLEAN := FALSE; > min: Target.Int := TInt.Zero; > max: Target.Int := TInt.Zero) = 1276c1301 < SimpleLoad (v, o, t); --- > SimpleLoad (v, o, t, min_valid, max_valid, min, max); 1291c1316 < SimpleLoad (v, o, best_type); --- > SimpleLoad (v, o, best_type, min_valid, max_valid, min, max); 1312c1337,1341 < PROCEDURE SimpleLoad (v: Var; o: Offset; t: Type) = --- > PROCEDURE SimpleLoad (v: Var; o: Offset; t: Type; > min_valid: BOOLEAN := FALSE; > max_valid: BOOLEAN := FALSE; > min: Target.Int := TInt.Zero; > max: Target.Int := TInt.Zero) = 1323a1353,1356 > x.min_valid := min_valid; > x.max_valid := max_valid; > x.min := min; > x.max := max; 1339a1373,1376 > x.min := TInt.Zero; > x.max := TInt.Zero; > x.min_valid := FALSE; > x.max_valid := FALSE; 1347a1385,1388 > stack[tos-1].min := TInt.Zero; > stack[tos-1].max := TInt.Zero; > stack[tos-1].min_valid := FALSE; > stack[tos-1].max_valid := FALSE; 1350c1391,1395 < PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0) = --- > PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0; > min_valid: BOOLEAN := FALSE; > max_valid: BOOLEAN := FALSE; > min: Target.Int := TInt.Zero; > max: Target.Int := TInt.Zero) = 1352c1397 < SimpleLoad (v, o, t); --- > SimpleLoad (v, o, t, min_valid, max_valid, min, max); 1815a1861,1864 > x.min_valid := TRUE; > x.max_valid := TRUE; > x.min := i; > x.max := i; 1832,1834c1881,2007 < BEGIN < IF Force_pair (commute := TRUE) THEN < op := M3CG.SwappedCompare [op]; --- > VAR always_true: BOOLEAN; > always_false: BOOLEAN; > left_type: Type; > right_type: Type; > left_min: Target.Int; > left_max: Target.Int; > right_min: Target.Int; > right_max: Target.Int; > left_signed: BOOLEAN; > right_signed: BOOLEAN; > BEGIN > > always_true := FALSE; > always_false := FALSE; > > WITH left = stack [SCheck (2, "Compare-left")], > right = stack [SCheck (1, "Compare-right")] DO > > left_type := left.type; > right_type := right.type; > > IF left.min_valid > AND left.max_valid > AND right.min_valid > AND right.max_valid > AND Target.OrdinalType[left_type] > AND Target.OrdinalType[right_type] THEN > > left_min := left.min; > left_max := left.max; > right_min := right.min; > right_max := right.max; > left_signed := Target.SignedType[left_type]; > right_signed := Target.SignedType[right_type]; > > (* First handle types that match in signedness. *) > > IF left_signed = right_signed THEN > > (* Check for ranges with no overlap. *) > > IF left_signed (* and right_signed *) THEN > IF TInt.LT(left_max, right_min) THEN > always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; > ELSIF TInt.GT(left_min, right_max) THEN > always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; > END; > ELSE (* left_signed and right_signed both false *) > IF TWord.LT(left_max, right_min) THEN > always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; > ELSIF TWord.GT(left_min, right_max) THEN > always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; > END; > END; > > (* Check for overlap just on the edge, e.g. [0..1] compared to [1..2]. *) > > IF NOT (always_true OR always_false) THEN > IF TInt.EQ(left_max, right_min) THEN > always_true := op = Cmp.LE; > always_false := op = Cmp.GT; > ELSIF TInt.EQ(left_min, right_max) THEN > always_true := op = Cmp.GE; > always_false := op = Cmp.LT; > END; > END; > > (* Handle equal subranges with one element, not likely to occur. *) > > IF NOT (always_true OR always_false) THEN > IF TInt.EQ(left_max, left_min) > AND TInt.EQ(left_max, right_max) > AND TInt.EQ(left_max, right_min) THEN > always_true := op IN SET OF Cmp{Cmp.GE, Cmp.LE, Cmp.EQ}; > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.GT, Cmp.NE}; > END; > END; > ELSE > > (* Now deal with mixed up types (signed compared to unsigned). > * We may be able to merge these by setting some min/max > * to zero. That is, the minimum of an unsigned type is zero. > * However we want to be sure not to interpret unsigned min/max > * as signed. > *) > > IF left_signed THEN > IF TInt.LT(left_max, TInt.Zero) THEN > always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; > ELSIF TInt.EQ(left_max, TInt.Zero) THEN > always_true := op = Cmp.LE; > always_false := op = Cmp.GT; > END; > ELSE (* right is signed *) > IF TInt.LT(right_max, TInt.Zero) THEN > always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; > ELSIF TInt.EQ(right_max, TInt.Zero) THEN > always_true := op = Cmp.GE; > always_false := op = Cmp.LT; > END; > END; > END; > END; > > <* ASSERT NOT (always_true AND always_false) *> > > IF always_true OR always_false THEN > Discard(right_type); > Discard(left_type); > IF always_true THEN > cg.load_integer (Target.Integer.cg_type, TInt.One); > ELSE > cg.load_integer (Target.Integer.cg_type, TInt.Zero); > END > ELSE > IF Force_pair (commute := TRUE) THEN > op := M3CG.SwappedCompare [op]; > END; > cg.compare (t, Target.Integer.cg_type, op); > SPop (2, "Compare"); > END; 1836,1837d2008 < cg.compare (t, Target.Integer.cg_type, op); < SPop (2, "Compare"); 2880a3052,3055 > x.min := TInt.Zero; > x.max := TInt.Zero; > x.min_valid := FALSE; > x.max_valid := FALSE; 2977c3152,3153 < BEGIN --- > BEGIN > debug := debug OR RTParams.IsPresent ("m3front_cg_debug"); Index: m3-sys/m3front/src/values/Variable.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/values/Variable.m3,v retrieving revision 1.13 diff -r1.13 Variable.m3 362a363,365 > VAR min: Target.Int; > max: Target.Int; > bounds_valid: BOOLEAN; 395c398,401 < CG.Load (t.cg_var, t.offset, t.size, t.cg_align, t.stk_type); --- > (*GetBounds (t, min, max); > bounds_valid := TInt.LE(min, max);*) > bounds_valid := t.tipe # NIL AND Type.GetBounds(t.tipe, min, max) AND TInt.LE(min, max); > CG.Load (t.cg_var, t.offset, t.size, t.cg_align, t.stk_type, bounds_valid, bounds_valid, min, max); -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Sun May 22 10:58:50 2011 From: jay.krell at cornell.edu (Jay K) Date: Sun, 22 May 2011 08:58:50 +0000 Subject: [M3devel] thread tester on 32bit Windows Message-ID: I'm not sure if I posted this. This is on Windows XP. C:\dev2\cm3.2\m3-libs\m3core\tests\thread>\bin\x86\cdb NT386\threadtest.exe @M3paranoidgc Microsoft (R) Windows Debugger Version 6.11.0001.404 X86 Copyright (c) Microsoft Corporation. All rights reserved. CommandLine: NT386\threadtest.exe @M3paranoidgc Symbol search path is: SRV*C:\symbols*http://msdl.microsoft.com/download/symbols Executable search path is: ModLoad: 00400000 00c7b000 threadtest.exe ModLoad: 7c900000 7c9b2000 ntdll.dll ModLoad: 7c800000 7c8f6000 C:\WINDOWS2\system32\kernel32.dll ModLoad: 78520000 785c3000 C:\WINDOWS2\WinSxS\x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.30729.4974_x-ww_d889290f\MSVCR90.dll (6ec.1010): Break instruction exception - code 80000003 (first chance) eax=00251eb4 ebx=7ffdf000 ecx=00000005 edx=00000020 esi=00251f48 edi=00251eb4 eip=7c90120e esp=0012fb20 ebp=0012fc94 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202 ntdll!DbgBreakPoint: 7c90120e cc int 3 0:000> .lines Line number information will be loaded 0:000> g Writing file...done Creating read threads...done Creating fork threads...done Creating alloc threads...done Creating lock threads...done running...printing oldest/median age/newest .(6ec.116c): Access violation - code c0000005 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=001ffffc ebx=00200000 ecx=00000002 edx=004317f0 esi=00380018 edi=00380018 eip=0043181c esp=0117fb98 ebp=0117fbc0 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010202 threadtest!RTCollector__RefSanityCheck+0x2c: 0043181c 8b18 mov ebx,dword ptr [eax] ds:0023:001ffffc=???????? 0:005> db @eax 001ffffc ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 0020000c ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 0020001c ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 0020002c ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 0020003c ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 0020004c ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 0020005c ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 0020006c ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 0:005> ~*k 0 Id: 6ec.1010 Suspend: 2 Teb: 7ffde000 Unfrozen ChildEBP RetAddr 0012fcd8 7c90d21a ntdll!KiFastSystemCallRet 0012fcdc 7c8023f1 ntdll!NtDelayExecution+0xc 0012fd34 7c802455 kernel32!SleepEx+0x61 0012fd44 0042bd6e kernel32!Sleep+0xf 0012fd84 0042bb47 threadtest!ThreadWin32__XPause+0x1c7 [..\src\thread\WIN32\ThreadWin32.m3 @ 765] 0012fda8 00404870 threadtest!Thread__Pause+0x31 [..\src\thread\WIN32\ThreadWin32.m3 @ 727] 0012fee4 00426c95 threadtest!Main_M3+0x13e2 [..\src\Main.m3 @ 558] 0012ff28 00426262 threadtest!RTLinker__RunMainBody+0x250 [..\src\runtime\common\RTLinker.m3 @ 406] 0012ff40 00426306 threadtest!RTLinker__AddUnitI+0xf7 [..\src\runtime\common\RTLinker.m3 @ 113] 0012ff60 00401038 threadtest!RTLinker__AddUnit+0x9c [..\src\runtime\common\RTLinker.m3 @ 122] 0012ff7c 00462900 threadtest!main+0x38 [_m3main.mc @ 4] 0012ffc0 7c817077 threadtest!__tmainCRTStartup+0x10f [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 582] 0012fff0 00000000 kernel32!BaseProcessStart+0x23 1 Id: 6ec.1168 Suspend: 2 Teb: 7ffdd000 Unfrozen ChildEBP RetAddr 00d7fc64 7c90df5a ntdll!KiFastSystemCallRet 00d7fc68 7c919b23 ntdll!NtWaitForSingleObject+0xc 00d7fcf0 7c901046 ntdll!RtlpWaitForCriticalSection+0x132 00d7fcf8 0042a153 ntdll!RtlEnterCriticalSection+0x46 00d7fd30 0042a830 threadtest!ThreadWin32__InitCondition+0xa1 [..\src\thread\WIN32\ThreadWin32.m3 @ 186] 00d7fd50 0042cc08 threadtest!Thread__Broadcast+0x3f [..\src\thread\WIN32\ThreadWin32.m3 @ 409] 00d7fd6c 004295f9 threadtest!RTOS__UnlockHeap+0xb3 [..\src\thread\WIN32\ThreadWin32.m3 @ 1181] 00d7fd88 00429586 threadtest!RTAllocator_M3_LINE_370+0x15 [..\src\runtime\common\RTAllocator.m3 @ 371] 00d7fdc8 00428ba8 threadtest!RTAllocator__AllocTraced+0x105 [..\src\runtime\common\RTAllocator.m3 @ 368] 00d7fdfc 004286dc threadtest!RTAllocator__GetTracedObj+0x86 [..\src\runtime\common\RTAllocator.m3 @ 224] 00d7fe18 00408679 threadtest!RTHooks__AllocateTracedObj+0x15 [..\src\runtime\common\RTAllocator.m3 @ 122] 00d7fe40 00401360 threadtest!FileRd__Open+0x19 [..\src\rw\FileRd.m3 @ 16] 00d7ff78 0042b5ff threadtest!Main__RApply+0x160 [..\src\Main.m3 @ 182] 00d7ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ThreadWin32.m3 @ 615] 00d7ffec 00000000 kernel32!BaseThreadStart+0x37 2 Id: 6ec.1174 Suspend: 2 Teb: 7ffdc000 Unfrozen ChildEBP RetAddr 00e7fc64 7c90df5a ntdll!KiFastSystemCallRet 00e7fc68 7c919b23 ntdll!NtWaitForSingleObject+0xc 00e7fcf0 7c901046 ntdll!RtlpWaitForCriticalSection+0x132 00e7fcf8 0042a153 ntdll!RtlEnterCriticalSection+0x46 00e7fd30 0042a830 threadtest!ThreadWin32__InitCondition+0xa1 [..\src\thread\WIN32\ThreadWin32.m3 @ 186] 00e7fd50 0042cc08 threadtest!Thread__Broadcast+0x3f [..\src\thread\WIN32\ThreadWin32.m3 @ 409] 00e7fd6c 004295f9 threadtest!RTOS__UnlockHeap+0xb3 [..\src\thread\WIN32\ThreadWin32.m3 @ 1181] 00e7fd88 00429586 threadtest!RTAllocator_M3_LINE_370+0x15 [..\src\runtime\common\RTAllocator.m3 @ 371] 00e7fdc8 00428ba8 threadtest!RTAllocator__AllocTraced+0x105 [..\src\runtime\common\RTAllocator.m3 @ 368] 00e7fdfc 004286dc threadtest!RTAllocator__GetTracedObj+0x86 [..\src\runtime\common\RTAllocator.m3 @ 224] 00e7fe18 00408679 threadtest!RTHooks__AllocateTracedObj+0x15 [..\src\runtime\common\RTAllocator.m3 @ 122] 00e7fe40 00401360 threadtest!FileRd__Open+0x19 [..\src\rw\FileRd.m3 @ 16] 00e7ff78 0042b5ff threadtest!Main__RApply+0x160 [..\src\Main.m3 @ 182] 00e7ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ThreadWin32.m3 @ 615] 00e7ffec 00000000 kernel32!BaseThreadStart+0x37 3 Id: 6ec.14cc Suspend: 2 Teb: 7ffdb000 Unfrozen ChildEBP RetAddr 00f7fd1c 7c90d0ba ntdll!KiFastSystemCallRet 00f7fd20 7c8109b6 ntdll!NtCreateFile+0xc 00f7fdb8 7c801a53 kernel32!CreateFileW+0x35f 00f7fddc 00417f10 kernel32!CreateFileA+0x30 00f7fe18 00408689 threadtest!FS__OpenFileReadonly+0x3c [..\src\os\WIN32\FSWin32.m3 @ 226] 00f7fe40 00401360 threadtest!FileRd__Open+0x29 [..\src\rw\FileRd.m3 @ 16] 00f7ff78 0042b5ff threadtest!Main__RApply+0x160 [..\src\Main.m3 @ 182] 00f7ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ ThreadWin32.m3 @ 615] 00f7ffec 00000000 kernel32!BaseThreadStart+0x37 4 Id: 6ec.d20 Suspend: 2 Teb: 7ffda000 Unfrozen ChildEBP RetAddr 0107fcf8 7c90df5a ntdll!KiFastSystemCallRet 0107fcfc 7c919b23 ntdll!NtWaitForSingleObject+0xc 0107fd84 7c901046 ntdll!RtlpWaitForCriticalSection+0x132 0107fd8c 0042cb42 ntdll!RtlEnterCriticalSection+0x46 0107fda0 0042954e threadtest!RTOS__LockHeap+0x2c [..\src\thread\WIN32\ThreadWin32.m3 @ 1168] 0107fde0 00428ba8 threadtest!RTAllocator__AllocTraced+0xcd [..\src\runtime\common\RTAllocator.m3 @ 367] 0107fe14 004286dc threadtest!RTAllocator__GetTracedObj+0x86 [..\src\runtime\common\RTAllocator.m3 @ 224] 0107fe30 00452f79 threadtest!RTHooks__AllocateTracedObj+0x15 [..\src\runtime\common\RTAllocator.m3 @ 122] 0107fe4c 0043e62a threadtest!Text8CString__New+0x19 [..\src\text\Text8CString.m3 @ 17] 0107fe64 0043cdf3 threadtest!M3toC__StoT+0x16 [..\src\C\Common\M3toC.m3 @ 96] 0107fe90 0040d037 threadtest!RTArgs__GetArg+0x6e [..\src\runtime\WIN32\RTArgs.m3 @ 139] 0107feb8 00401d6a threadtest!Params__Get+0x57 [..\src\params\Params.m3 @ 18] 0107ff78 0042b5ff threadtest!Main__FApply+0x141 [..\src\Main.m3 @ 245] 0107ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ThreadWin32.m3 @ 615] 0107ffec 00000000 kernel32!BaseThreadStart+0x37 # 5 Id: 6ec.116c Suspend: 1 Teb: 7ffd9000 Unfrozen ChildEBP RetAddr 0117fbc0 0044fbdc threadtest!RTCollector__RefSanityCheck+0x2c [..\src\runtime\common\RTCollector.m3 @ 1702] 0117fc04 0044f4df threadtest!RTHeapMap__Walk+0x448 [..\src\runtime\common\RTHeapMap.m3 @ 202] 0117fc28 0044f4ba threadtest!RTHeapMap__DoWalkRef+0x62 [..\src\runtime\common\RTHeapMap.m3 @ 62] 0117fc4c 0044f4ba threadtest!RTHeapMap__DoWalkRef+0x3d [..\src\runtime\common\RTHeapMap.m3 @ 57] 0117fc70 0044f475 threadtest!RTHeapMap__DoWalkRef+0x3d [..\src\runtime\common\RTHeapMap.m3 @ 57] 0117fc9c 00431607 threadtest!RTHeapMap__WalkRef+0xf5 [..\src\runtime\common\RTHeapMap.m3 @ 47] 0117fcd8 0044eab4 threadtest!RTCollector__SanityCheck+0x23c [..\src\runtime\common\RTCollector.m3 @ 1660] 0117fcf8 0042f379 threadtest!RTHeapRep__InvokeMonitors+0x84 [..\src\runtime\common\RTHeapRep.m3 @ 56] 0117fd4c 0042f15e threadtest!RTCollector__CollectSomeInStateZero+0x1e0 [..\src\runtime\common\RTCollector.m3 @ 786] 0117fd5c 0042edfc threadtest!RTCollector__CollectSome+0x6e [..\src\runtime\common\RTCollector.m3 @ 720] 0117fda0 00429554 threadtest!RTHeapRep__CollectEnough+0x9b [..\src\runtime\common\RTCollector.m3 @ 655] 0117fde0 00428ba8 threadtest!RTAllocator__AllocTraced+0xd3 [..\src\runtime\common\RTAllocator.m3 @ 368] 0117fe14 004286dc threadtest!RTAllocator__GetTracedObj+0x86 [..\src\runtime\common\RTAllocator.m3 @ 224] 0117fe30 00452f79 threadtest!RTHooks__AllocateTracedObj+0x15 [..\src\runtime\common\RTAllocator.m3 @ 122] 0117fe4c 0043e62a threadtest!Text8CString__New+0x19 [..\src\text\Text8CString.m3 @ 17] 0117fe64 0043cdf3 threadtest!M3toC__StoT+0x16 [..\src\C\Common\M3toC.m3 @ 96] 0117fe90 0040d037 threadtest!RTArgs__GetArg+0x6e [..\src\runtime\WIN32\RTArgs.m3 @ 139] 0117feb8 00401d6a threadtest!Params__Get+0x57 [..\src\params\Params.m3 @ 18] 0117ff78 0042b5ff threadtest!Main__FApply+0x141 [..\src\Main.m3 @ 245] 0117ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ThreadWin32.m3 @ 615] 6 Id: 6ec.11b4 Suspend: 2 Teb: 7ffd8000 Unfrozen ChildEBP RetAddr 0127fcf8 7c90df5a ntdll!KiFastSystemCallRet 0127fcfc 7c919b23 ntdll!NtWaitForSingleObject+0xc 0127fd84 7c901046 ntdll!RtlpWaitForCriticalSection+0x132 0127fd8c 0042cb42 ntdll!RtlEnterCriticalSection+0x46 0127fda0 0042954e threadtest!RTOS__LockHeap+0x2c [..\src\thread\WIN32\ThreadWin32.m3 @ 1168] 0127fde0 00428ba8 threadtest!RTAllocator__AllocTraced+0xcd [..\src\runtime\common\RTAllocator.m3 @ 367] 0127fe14 004286dc threadtest!RTAllocator__GetTracedObj+0x86 [..\src\runtime\common\RTAllocator.m3 @ 224] 0127fe30 00452f79 threadtest!RTHooks__AllocateTracedObj+0x15 [..\src\runtime\common\RTAllocator.m3 @ 122] 0127fe4c 0043e62a threadtest!Text8CString__New+0x19 [..\src\text\Text8CString.m3 @ 17] 0127fe64 0043cdf3 threadtest!M3toC__StoT+0x16 [..\src\C\Common\M3toC.m3 @ 96] 0127fe90 0040d037 threadtest!RTArgs__GetArg+0x6e [..\src\runtime\WIN32\RTArgs.m3 @ 139] 0127feb8 00401d6a threadtest!Params__Get+0x57 [..\src\params\Params.m3 @ 18] 0127ff78 0042b5ff threadtest!Main__FApply+0x141 [..\src\Main.m3 @ 245] 0127ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ThreadWin32.m3 @ 615] 0127ffec 00000000 kernel32!BaseThreadStart+0x37 7 Id: 6ec.1038 Suspend: 2 Teb: 7ffd7000 Unfrozen ChildEBP RetAddr 0137fdd4 7c90df5a ntdll!KiFastSystemCallRet 0137fdd8 7c919b23 ntdll!NtWaitForSingleObject+0xc 0137fe60 7c901046 ntdll!RtlpWaitForCriticalSection+0x132 0137fe68 0042cb42 ntdll!RtlEnterCriticalSection+0x46 0137fe7c 0042954e threadtest!RTOS__LockHeap+0x2c [..\src\thread\WIN32\ThreadWin32.m3 @ 1168] 0137febc 004290fd threadtest!RTAllocator__AllocTraced+0xcd [..\src\runtime\common\RTAllocator.m3 @ 367] 0137fef8 00428788 threadtest!RTAllocator__GetOpenArray+0x91 [..\src\runtime\common\RTAllocator.m3 @ 296] 0137ff1c 00402430 threadtest!RTHooks__AllocateOpenArray+0x19 [..\src\runtime\common\RTAllocator.m3 @ 143] 0137ff78 0042b5ff threadtest!Main__AApply+0x128 [..\src\Main.m3 @ 283] 0137ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ThreadWin32.m3 @ 615] 0137ffec 00000000 kernel32!BaseThreadStart+0x37 8 Id: 6ec.1034 Suspend: 2 Teb: 7ffd6000 Unfrozen ChildEBP RetAddr 0147fdd4 7c90df5a ntdll!KiFastSystemCallRet 0147fdd8 7c919b23 ntdll!NtWaitForSingleObject+0xc 0147fe60 7c901046 ntdll!RtlpWaitForCriticalSection+0x132 0147fe68 0042cb42 ntdll!RtlEnterCriticalSection+0x46 0147fe7c 0042954e threadtest!RTOS__LockHeap+0x2c [..\src\thread\WIN32\ThreadWin32.m3 @ 1168] 0147febc 004290fd threadtest!RTAllocator__AllocTraced+0xcd [..\src\runtime\common\RTAllocator.m3 @ 367] 0147fef8 00428788 threadtest!RTAllocator__GetOpenArray+0x91 [..\src\runtime\common\RTAllocator.m3 @ 296] 0147ff1c 00402430 threadtest!RTHooks__AllocateOpenArray+0x19 [..\src\runtime\common\RTAllocator.m3 @ 143] 0147ff78 0042b5ff threadtest!Main__AApply+0x128 [..\src\Main.m3 @ 283] 0147ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ThreadWin32.m3 @ 615] 0147ffec 00000000 kernel32!BaseThreadStart+0x37 9 Id: 6ec.10d0 Suspend: 2 Teb: 7ffd5000 Unfrozen ChildEBP RetAddr 0157fdd4 7c90df5a ntdll!KiFastSystemCallRet 0157fdd8 7c919b23 ntdll!NtWaitForSingleObject+0xc 0157fe60 7c901046 ntdll!RtlpWaitForCriticalSection+0x132 0157fe68 0042cb42 ntdll!RtlEnterCriticalSection+0x46 0157fe7c 0042954e threadtest!RTOS__LockHeap+0x2c [..\src\thread\WIN32\ThreadWin32.m3 @ 1168] 0157febc 004290fd threadtest!RTAllocator__AllocTraced+0xcd [..\src\runtime\common\RTAllocator.m3 @ 367] 0157fef8 00428788 threadtest!RTAllocator__GetOpenArray+0x91 [..\src\runtime\common\RTAllocator.m3 @ 296] 0157ff1c 00402430 threadtest!RTHooks__AllocateOpenArray+0x19 [..\src\runtime\common\RTAllocator.m3 @ 143] 0157ff78 0042b5ff threadtest!Main__AApply+0x128 [..\src\Main.m3 @ 283] 0157ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ThreadWin32.m3 @ 615] 0157ffec 00000000 kernel32!BaseThreadStart+0x37 10 Id: 6ec.ff8 Suspend: 2 Teb: 7ffd4000 Unfrozen ChildEBP RetAddr 0167fe48 7c90df5a ntdll!KiFastSystemCallRet 0167fe4c 7c919b23 ntdll!NtWaitForSingleObject+0xc 0167fed4 7c901046 ntdll!RtlpWaitForCriticalSection+0x132 0167fedc 00429f52 ntdll!RtlEnterCriticalSection+0x46 0167ff10 0042a287 threadtest!ThreadWin32__InitMutex+0x53 [..\src\thread\WIN32\ThreadWin32.m3 @ 148] 0167ff28 00402a5f threadtest!ThreadWin32__LockMutex+0x3f [..\src\thread\WIN32\ThreadWin32.m3 @ 210] 0167ff78 0042b5ff threadtest!Main__LApply+0x15f [..\src\Main.m3 @ 319] 0167ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ThreadWin32.m3 @ 615] 0167ffec 00000000 kernel32!BaseThreadStart+0x37 11 Id: 6ec.10e8 Suspend: 2 Teb: 7ffaf000 Unfrozen ChildEBP RetAddr 0177fdfc 7c90df5a ntdll!KiFastSystemCallRet 0177fe00 7c919b23 ntdll!NtWaitForSingleObject+0xc 0177fe88 7c901046 ntdll!RtlpWaitForCriticalSection+0x132 0177fe90 0042cb42 ntdll!RtlEnterCriticalSection+0x46 0177fea4 004332ce threadtest!RTOS__LockHeap+0x2c [..\src\thread\WIN32\ThreadWin2.m3 @ 1168] 0177fed8 00429faf threadtest!RTHeapRep__RegisterFinalCleanup+0x73 [..\src\runtime\common\RTCollector.m3 @ 2150] 0177ff10 0042a287 threadtest!ThreadWin32__InitMutex+0xb0 [..\src\thread\WIN32\ThreadWin32.m3 @ 156] 0177ff28 00402a5f threadtest!ThreadWin32__LockMutex+0x3f [..\src\thread\WIN32\ThreadWin32.m3 @ 210] 0177ff78 0042b5ff threadtest!Main__LApply+0x15f [..\src\Main.m3 @ 319] 0177ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ThreadWin32.m3 @ 615] 0177ffec 00000000 kernel32!BaseThreadStart+0x37 12 Id: 6ec.10d8 Suspend: 2 Teb: 7ffae000 Unfrozen ChildEBP RetAddr 0187fe48 7c90df5a ntdll!KiFastSystemCallRet 0187fe4c 7c919b23 ntdll!NtWaitForSingleObject+0xc 0187fed4 7c901046 ntdll!RtlpWaitForCriticalSection+0x132 0187fedc 00429f52 ntdll!RtlEnterCriticalSection+0x46 0187ff10 0042a287 threadtest!ThreadWin32__InitMutex+0x53 [..\src\thread\WIN32\ThreadWin32.m3 @ 148] 0187ff28 00402a5f threadtest!ThreadWin32__LockMutex+0x3f [..\src\thread\WIN32\ThreadWin32.m3 @ 210] 0187ff78 0042b5ff threadtest!Main__LApply+0x15f [..\src\Main.m3 @ 319] 0187ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ThreadWin32.m3 @ 615] 0187ffec 00000000 kernel32!BaseThreadStart+0x37 0:005> I suspect more logging/tracing is needed, to see what was moved where. - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Sun May 22 20:51:08 2011 From: hosking at cs.purdue.edu (Tony Hosking) Date: Sun, 22 May 2011 14:51:08 -0400 Subject: [M3devel] range analysis? In-Reply-To: References: Message-ID: <7FF8F0BA-AEC4-40DB-98A0-E1206985A72E@cs.purdue.edu> This is problematic. On May 22, 2011, at 4:26 AM, Jay K wrote: > The code assumes the minimum of a type is less than or equal to its maximum. -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Sun May 22 20:51:59 2011 From: hosking at cs.purdue.edu (Tony Hosking) Date: Sun, 22 May 2011 14:51:59 -0400 Subject: [M3devel] range analysis? In-Reply-To: References: Message-ID: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> So, one question is: what benefit does this really give? Your examples seem a little contrived. On May 22, 2011, at 4:26 AM, Jay K wrote: > I've been sitting on this diff a long while. > > In some places the frontend knows the bounds of a type/value and > will optimize away range checks. I'm pretty sure. > > > > This makes it do that more. > > > I haven't looked at or tested this in ages. > But the basic idea seems sound, simple, easy enough to get a few small wins from. > > For example if you have: > > a: [-10..-1]; > b: [1..10]; > > then all comparisons between a and b are compile-time constant. > > Comparisons of cardinals to negative numbers, likewise. > > One thing maybe missing below is handling of empty ranges like > a: [1..-1]; > > The code assumes the minimum of a type is less than or equal to its maximum. > > > Index: m3-sys/m3front/src/misc/CG.i3 > =================================================================== > RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.i3,v > retrieving revision 1.15 > diff -r1.15 CG.i3 > 11c11 > < IMPORT Target, M3CG, M3; > --- > > IMPORT Target, M3CG, M3, TInt; > 402c402,406 > < PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type); > --- > > PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type; > > min_valid: BOOLEAN := FALSE; > > max_valid: BOOLEAN := FALSE; > > min: Target.Int := TInt.Zero; > > max: Target.Int := TInt.Zero); > 414,415c418,423 > < PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0); > < (* == Load (v, o, t.size, t.align, t) *) > --- > > PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0; > > min_valid: BOOLEAN := FALSE; > > max_valid: BOOLEAN := FALSE; > > min: Target.Int := TInt.Zero; > > max: Target.Int := TInt.Zero); > > (* == Load (v, o, t.size, t.align, t, min/max...) *) > Index: m3-sys/m3front/src/misc/CG.m3 > =================================================================== > RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.m3,v > retrieving revision 1.40 > diff -r1.40 CG.m3 > 13c13 > < IMPORT M3, M3CG, M3CG_Ops, M3CG_Check; > --- > > IMPORT M3, M3CG, M3CG_Ops, M3CG_Check, RTIO, RTParams; > 45a46,49 > > min_valid : BOOLEAN := FALSE; (* whether or not min is valid *) > > max_valid : BOOLEAN := FALSE; (* whether or not max is valid *) > > min : Target.Int := TInt.Zero; (* the minimum possible value *) > > max : Target.Int := TInt.Zero; (* the maximum possible value *) > 80c84,85 > < VAR > --- > > VAR > > debug := FALSE; > 604a610,614 > > v.min := TInt.Zero; > > v.max := TInt.Zero; > > v.min_valid := FALSE; > > v.max_valid := FALSE; > > > 766a777,780 > > x.min := TInt.Zero; > > x.max := TInt.Zero; > > x.min_valid := FALSE; > > x.max_valid := FALSE; > 978a993,995 > > IF debug THEN > > RTIO.PutText("m3front:cg:Init_int:NOT in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); > > END; > 980a998,1001 > > END; > > > > IF debug THEN > > RTIO.PutText("m3front:cg:Init_int:in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); > 1266c1287,1291 > < PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type) = > --- > > PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type; > > min_valid: BOOLEAN := FALSE; > > max_valid: BOOLEAN := FALSE; > > min: Target.Int := TInt.Zero; > > max: Target.Int := TInt.Zero) = > 1276c1301 > < SimpleLoad (v, o, t); > --- > > SimpleLoad (v, o, t, min_valid, max_valid, min, max); > 1291c1316 > < SimpleLoad (v, o, best_type); > --- > > SimpleLoad (v, o, best_type, min_valid, max_valid, min, max); > 1312c1337,1341 > < PROCEDURE SimpleLoad (v: Var; o: Offset; t: Type) = > --- > > PROCEDURE SimpleLoad (v: Var; o: Offset; t: Type; > > min_valid: BOOLEAN := FALSE; > > max_valid: BOOLEAN := FALSE; > > min: Target.Int := TInt.Zero; > > max: Target.Int := TInt.Zero) = > 1323a1353,1356 > > x.min_valid := min_valid; > > x.max_valid := max_valid; > > x.min := min; > > x.max := max; > 1339a1373,1376 > > x.min := TInt.Zero; > > x.max := TInt.Zero; > > x.min_valid := FALSE; > > x.max_valid := FALSE; > 1347a1385,1388 > > stack[tos-1].min := TInt.Zero; > > stack[tos-1].max := TInt.Zero; > > stack[tos-1].min_valid := FALSE; > > stack[tos-1].max_valid := FALSE; > 1350c1391,1395 > < PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0) = > --- > > PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0; > > min_valid: BOOLEAN := FALSE; > > max_valid: BOOLEAN := FALSE; > > min: Target.Int := TInt.Zero; > > max: Target.Int := TInt.Zero) = > 1352c1397 > < SimpleLoad (v, o, t); > --- > > SimpleLoad (v, o, t, min_valid, max_valid, min, max); > 1815a1861,1864 > > x.min_valid := TRUE; > > x.max_valid := TRUE; > > x.min := i; > > x.max := i; > 1832,1834c1881,2007 > < BEGIN > < IF Force_pair (commute := TRUE) THEN > < op := M3CG.SwappedCompare [op]; > --- > > VAR always_true: BOOLEAN; > > always_false: BOOLEAN; > > left_type: Type; > > right_type: Type; > > left_min: Target.Int; > > left_max: Target.Int; > > right_min: Target.Int; > > right_max: Target.Int; > > left_signed: BOOLEAN; > > right_signed: BOOLEAN; > > BEGIN > > > > always_true := FALSE; > > always_false := FALSE; > > > > WITH left = stack [SCheck (2, "Compare-left")], > > right = stack [SCheck (1, "Compare-right")] DO > > > > left_type := left.type; > > right_type := right.type; > > > > IF left.min_valid > > AND left.max_valid > > AND right.min_valid > > AND right.max_valid > > AND Target.OrdinalType[left_type] > > AND Target.OrdinalType[right_type] THEN > > > > left_min := left.min; > > left_max := left.max; > > right_min := right.min; > > right_max := right.max; > > left_signed := Target.SignedType[left_type]; > > right_signed := Target.SignedType[right_type]; > > > > (* First handle types that match in signedness. *) > > > > IF left_signed = right_signed THEN > > > > (* Check for ranges with no overlap. *) > > > > IF left_signed (* and right_signed *) THEN > > IF TInt.LT(left_max, right_min) THEN > > always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; > > always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; > > ELSIF TInt.GT(left_min, right_max) THEN > > always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; > > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; > > END; > > ELSE (* left_signed and right_signed both false *) > > IF TWord.LT(left_max, right_min) THEN > > always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; > > always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; > > ELSIF TWord.GT(left_min, right_max) THEN > > always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; > > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; > > END; > > END; > > > > (* Check for overlap just on the edge, e.g. [0..1] compared to [1..2]. *) > > > > IF NOT (always_true OR always_false) THEN > > IF TInt.EQ(left_max, right_min) THEN > > always_true := op = Cmp.LE; > > always_false := op = Cmp.GT; > > ELSIF TInt.EQ(left_min, right_max) THEN > > always_true := op = Cmp.GE; > > always_false := op = Cmp.LT; > > END; > > END; > > > > (* Handle equal subranges with one element, not likely to occur. *) > > > > IF NOT (always_true OR always_false) THEN > > IF TInt.EQ(left_max, left_min) > > AND TInt.EQ(left_max, right_max) > > AND TInt.EQ(left_max, right_min) THEN > > always_true := op IN SET OF Cmp{Cmp.GE, Cmp.LE, Cmp.EQ}; > > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.GT, Cmp.NE}; > > END; > > END; > > ELSE > > > > (* Now deal with mixed up types (signed compared to unsigned). > > * We may be able to merge these by setting some min/max > > * to zero. That is, the minimum of an unsigned type is zero. > > * However we want to be sure not to interpret unsigned min/max > > * as signed. > > *) > > > > IF left_signed THEN > > IF TInt.LT(left_max, TInt.Zero) THEN > > always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; > > always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; > > ELSIF TInt.EQ(left_max, TInt.Zero) THEN > > always_true := op = Cmp.LE; > > always_false := op = Cmp.GT; > > END; > > ELSE (* right is signed *) > > IF TInt.LT(right_max, TInt.Zero) THEN > > always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; > > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; > > ELSIF TInt.EQ(right_max, TInt.Zero) THEN > > always_true := op = Cmp.GE; > > always_false := op = Cmp.LT; > > END; > > END; > > END; > > END; > > > > <* ASSERT NOT (always_true AND always_false) *> > > > > IF always_true OR always_false THEN > > Discard(right_type); > > Discard(left_type); > > IF always_true THEN > > cg.load_integer (Target.Integer.cg_type, TInt.One); > > ELSE > > cg.load_integer (Target.Integer.cg_type, TInt.Zero); > > END > > ELSE > > IF Force_pair (commute := TRUE) THEN > > op := M3CG.SwappedCompare [op]; > > END; > > cg.compare (t, Target.Integer.cg_type, op); > > SPop (2, "Compare"); > > END; > 1836,1837d2008 > < cg.compare (t, Target.Integer.cg_type, op); > < SPop (2, "Compare"); > 2880a3052,3055 > > x.min := TInt.Zero; > > x.max := TInt.Zero; > > x.min_valid := FALSE; > > x.max_valid := FALSE; > 2977c3152,3153 > < BEGIN > --- > > BEGIN > > debug := debug OR RTParams.IsPresent ("m3front_cg_debug"); > Index: m3-sys/m3front/src/values/Variable.m3 > =================================================================== > RCS file: /usr/cvs/cm3/m3-sys/m3front/src/values/Variable.m3,v > retrieving revision 1.13 > diff -r1.13 Variable.m3 > 362a363,365 > > VAR min: Target.Int; > > max: Target.Int; > > bounds_valid: BOOLEAN; > 395c398,401 > < CG.Load (t.cg_var, t.offset, t.size, t.cg_align, t.stk_type); > --- > > (*GetBounds (t, min, max); > > bounds_valid := TInt.LE(min, max);*) > > bounds_valid := t.tipe # NIL AND Type.GetBounds(t.tipe, min, max) AND TInt.LE(min, max); > > CG.Load (t.cg_var, t.offset, t.size, t.cg_align, t.stk_type, bounds_valid, bounds_valid, min, max); > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Mon May 23 01:18:02 2011 From: jay.krell at cornell.edu (Jay K) Date: Sun, 22 May 2011 23:18:02 +0000 Subject: [M3devel] range analysis? In-Reply-To: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> References: , <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> Message-ID: Well, I can build the whole tree and see how many times it helps. I think this is a pretty standard optimization technique. Though it'd work better with compiler-derived additional information. I initially happened upon this idea developing test cases. > The code assumes the minimum of a type is less than or equal to its maximum. I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. - Jay Subject: Re: range analysis? From: hosking at cs.purdue.edu Date: Sun, 22 May 2011 14:51:59 -0400 CC: m3devel at elegosoft.com To: jay.krell at cornell.edu So, one question is: what benefit does this really give? Your examples seem a little contrived. On May 22, 2011, at 4:26 AM, Jay K wrote:I've been sitting on this diff a long while. In some places the frontend knows the bounds of a type/value and will optimize away range checks. I'm pretty sure. This makes it do that more. I haven't looked at or tested this in ages. But the basic idea seems sound, simple, easy enough to get a few small wins from. For example if you have: a: [-10..-1]; b: [1..10]; then all comparisons between a and b are compile-time constant. Comparisons of cardinals to negative numbers, likewise. One thing maybe missing below is handling of empty ranges like a: [1..-1]; The code assumes the minimum of a type is less than or equal to its maximum. Index: m3-sys/m3front/src/misc/CG.i3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.i3,v retrieving revision 1.15 diff -r1.15 CG.i3 11c11 < IMPORT Target, M3CG, M3; --- > IMPORT Target, M3CG, M3, TInt; 402c402,406 < PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type); --- > PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type; > min_valid: BOOLEAN := FALSE; > max_valid: BOOLEAN := FALSE; > min: Target.Int := TInt.Zero; > max: Target.Int := TInt.Zero); 414,415c418,423 < PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0); < (* == Load (v, o, t.size, t.align, t) *) --- > PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0; > min_valid: BOOLEAN := FALSE; > max_valid: BOOLEAN := FALSE; > min: Target.Int := TInt.Zero; > max: Target.Int := TInt.Zero); > (* == Load (v, o, t.size, t.align, t, min/max...) *) Index: m3-sys/m3front/src/misc/CG.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.m3,v retrieving revision 1.40 diff -r1.40 CG.m3 13c13 < IMPORT M3, M3CG, M3CG_Ops, M3CG_Check; --- > IMPORT M3, M3CG, M3CG_Ops, M3CG_Check, RTIO, RTParams; 45a46,49 > min_valid : BOOLEAN := FALSE; (* whether or not min is valid *) > max_valid : BOOLEAN := FALSE; (* whether or not max is valid *) > min : Target.Int := TInt.Zero; (* the minimum possible value *) > max : Target.Int := TInt.Zero; (* the maximum possible value *) 80c84,85 < VAR --- > VAR > debug := FALSE; 604a610,614 > v.min := TInt.Zero; > v.max := TInt.Zero; > v.min_valid := FALSE; > v.max_valid := FALSE; > 766a777,780 > x.min := TInt.Zero; > x.max := TInt.Zero; > x.min_valid := FALSE; > x.max_valid := FALSE; 978a993,995 > IF debug THEN > RTIO.PutText("m3front:cg:Init_int:NOT in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); > END; 980a998,1001 > END; > > IF debug THEN > RTIO.PutText("m3front:cg:Init_int:in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); 1266c1287,1291 < PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type) = --- > PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type; > min_valid: BOOLEAN := FALSE; > max_valid: BOOLEAN := FALSE; > min: Target.Int := TInt.Zero; > max: Target.Int := TInt.Zero) = 1276c1301 < SimpleLoad (v, o, t); --- > SimpleLoad (v, o, t, min_valid, max_valid, min, max); 1291c1316 < SimpleLoad (v, o, best_type); --- > SimpleLoad (v, o, best_type, min_valid, max_valid, min, max); 1312c1337,1341 < PROCEDURE SimpleLoad (v: Var; o: Offset; t: Type) = --- > PROCEDURE SimpleLoad (v: Var; o: Offset; t: Type; > min_valid: BOOLEAN := FALSE; > max_valid: BOOLEAN := FALSE; > min: Target.Int := TInt.Zero; > max: Target.Int := TInt.Zero) = 1323a1353,1356 > x.min_valid := min_valid; > x.max_valid := max_valid; > x.min := min; > x.max := max; 1339a1373,1376 > x.min := TInt.Zero; > x.max := TInt.Zero; > x.min_valid := FALSE; > x.max_valid := FALSE; 1347a1385,1388 > stack[tos-1].min := TInt.Zero; > stack[tos-1].max := TInt.Zero; > stack[tos-1].min_valid := FALSE; > stack[tos-1].max_valid := FALSE; 1350c1391,1395 < PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0) = --- > PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0; > min_valid: BOOLEAN := FALSE; > max_valid: BOOLEAN := FALSE; > min: Target.Int := TInt.Zero; > max: Target.Int := TInt.Zero) = 1352c1397 < SimpleLoad (v, o, t); --- > SimpleLoad (v, o, t, min_valid, max_valid, min, max); 1815a1861,1864 > x.min_valid := TRUE; > x.max_valid := TRUE; > x.min := i; > x.max := i; 1832,1834c1881,2007 < BEGIN < IF Force_pair (commute := TRUE) THEN < op := M3CG.SwappedCompare [op]; --- > VAR always_true: BOOLEAN; > always_false: BOOLEAN; > left_type: Type; > right_type: Type; > left_min: Target.Int; > left_max: Target.Int; > right_min: Target.Int; > right_max: Target.Int; > left_signed: BOOLEAN; > right_signed: BOOLEAN; > BEGIN > > always_true := FALSE; > always_false := FALSE; > > WITH left = stack [SCheck (2, "Compare-left")], > right = stack [SCheck (1, "Compare-right")] DO > > left_type := left.type; > right_type := right.type; > > IF left.min_valid > AND left.max_valid > AND right.min_valid > AND right.max_valid > AND Target.OrdinalType[left_type] > AND Target.OrdinalType[right_type] THEN > > left_min := left.min; > left_max := left.max; > right_min := right.min; > right_max := right.max; > left_signed := Target.SignedType[left_type]; > right_signed := Target.SignedType[right_type]; > > (* First handle types that match in signedness. *) > > IF left_signed = right_signed THEN > > (* Check for ranges with no overlap. *) > > IF left_signed (* and right_signed *) THEN > IF TInt.LT(left_max, right_min) THEN > always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; > ELSIF TInt.GT(left_min, right_max) THEN > always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; > END; > ELSE (* left_signed and right_signed both false *) > IF TWord.LT(left_max, right_min) THEN > always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; > ELSIF TWord.GT(left_min, right_max) THEN > always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; > END; > END; > > (* Check for overlap just on the edge, e.g. [0..1] compared to [1..2]. *) > > IF NOT (always_true OR always_false) THEN > IF TInt.EQ(left_max, right_min) THEN > always_true := op = Cmp.LE; > always_false := op = Cmp.GT; > ELSIF TInt.EQ(left_min, right_max) THEN > always_true := op = Cmp.GE; > always_false := op = Cmp.LT; > END; > END; > > (* Handle equal subranges with one element, not likely to occur. *) > > IF NOT (always_true OR always_false) THEN > IF TInt.EQ(left_max, left_min) > AND TInt.EQ(left_max, right_max) > AND TInt.EQ(left_max, right_min) THEN > always_true := op IN SET OF Cmp{Cmp.GE, Cmp.LE, Cmp.EQ}; > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.GT, Cmp.NE}; > END; > END; > ELSE > > (* Now deal with mixed up types (signed compared to unsigned). > * We may be able to merge these by setting some min/max > * to zero. That is, the minimum of an unsigned type is zero. > * However we want to be sure not to interpret unsigned min/max > * as signed. > *) > > IF left_signed THEN > IF TInt.LT(left_max, TInt.Zero) THEN > always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; > ELSIF TInt.EQ(left_max, TInt.Zero) THEN > always_true := op = Cmp.LE; > always_false := op = Cmp.GT; > END; > ELSE (* right is signed *) > IF TInt.LT(right_max, TInt.Zero) THEN > always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; > ELSIF TInt.EQ(right_max, TInt.Zero) THEN > always_true := op = Cmp.GE; > always_false := op = Cmp.LT; > END; > END; > END; > END; > > <* ASSERT NOT (always_true AND always_false) *> > > IF always_true OR always_false THEN > Discard(right_type); > Discard(left_type); > IF always_true THEN > cg.load_integer (Target.Integer.cg_type, TInt.One); > ELSE > cg.load_integer (Target.Integer.cg_type, TInt.Zero); > END > ELSE > IF Force_pair (commute := TRUE) THEN > op := M3CG.SwappedCompare [op]; > END; > cg.compare (t, Target.Integer.cg_type, op); > SPop (2, "Compare"); > END; 1836,1837d2008 < cg.compare (t, Target.Integer.cg_type, op); < SPop (2, "Compare"); 2880a3052,3055 > x.min := TInt.Zero; > x.max := TInt.Zero; > x.min_valid := FALSE; > x.max_valid := FALSE; 2977c3152,3153 < BEGIN --- > BEGIN > debug := debug OR RTParams.IsPresent ("m3front_cg_debug"); Index: m3-sys/m3front/src/values/Variable.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/values/Variable.m3,v retrieving revision 1.13 diff -r1.13 Variable.m3 362a363,365 > VAR min: Target.Int; > max: Target.Int; > bounds_valid: BOOLEAN; 395c398,401 < CG.Load (t.cg_var, t.offset, t.size, t.cg_align, t.stk_type); --- > (*GetBounds (t, min, max); > bounds_valid := TInt.LE(min, max);*) > bounds_valid := t.tipe # NIL AND Type.GetBounds(t.tipe, min, max) AND TInt.LE(min, max); > CG.Load (t.cg_var, t.offset, t.size, t.cg_align, t.stk_type, bounds_valid, bounds_valid, min, max); -------------- next part -------------- An HTML attachment was scrubbed... URL: From hendrik at topoi.pooq.com Mon May 23 14:41:53 2011 From: hendrik at topoi.pooq.com (Hendrik Boom) Date: Mon, 23 May 2011 08:41:53 -0400 Subject: [M3devel] range analysis? In-Reply-To: References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> Message-ID: <20110523124153.GA31229@topoi.pooq.com> On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: > > Well, I can build the whole tree and see how many times it helps. > I think this is a pretty standard optimization technique. > Though it'd work better with compiler-derived additional information. > > I initially happened upon this idea developing test cases. > > > The code assumes the minimum of a type is less than or equal to its maximum. > > I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. What *is* the semantics of a range whose minimum is greater than its maximum? There plainly can't be any values in this range. How is a variable of this tyoe initialized? Not to some arbitrary value of the type, because there aren't any. I can see this type being useful to admit convenient generalizations -- for example, an array with n elements can still exist if n happens to be zero, but it seems to me that any code involving a value of the range for subscripts for this array must be simple unexecutable. Or is there some latitude available in the principle that a value of a variable must always be of the correct type? -- hendrik From hosking at cs.purdue.edu Mon May 23 16:31:24 2011 From: hosking at cs.purdue.edu (Tony Hosking) Date: Mon, 23 May 2011 10:31:24 -0400 Subject: [M3devel] range analysis? In-Reply-To: <20110523124153.GA31229@topoi.pooq.com> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> Message-ID: <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> An empty subrange gives a warning in the compiler. But, the semantics is that it is empty, and has no values of the type. You cannot allocate (NEW) an empty type. You cannot declare a field of empty type. Nor can you declare a variable of empty type. On May 23, 2011, at 8:41 AM, Hendrik Boom wrote: > On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: >> >> Well, I can build the whole tree and see how many times it helps. >> I think this is a pretty standard optimization technique. >> Though it'd work better with compiler-derived additional information. >> >> I initially happened upon this idea developing test cases. >> >>> The code assumes the minimum of a type is less than or equal to its maximum. >> >> I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. > > What *is* the semantics of a range whose minimum is greater than its > maximum? There plainly can't be any values in this range. How is a > variable of this tyoe initialized? Not to some arbitrary value of the > type, because there aren't any. I can see this type being useful to > admit convenient generalizations -- for example, an array with n > elements can still exist if n happens to be zero, but it seems to me > that any code involving a value of the range for subscripts for this > array must be simple unexecutable. > > Or is there some latitude available in the principle that a value of a > variable must always be of the correct type? > > -- hendrik From rodney_bates at lcwb.coop Mon May 23 18:45:14 2011 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Mon, 23 May 2011 11:45:14 -0500 Subject: [M3devel] range analysis? In-Reply-To: <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> Message-ID: <4DDA8F1A.3070207@lcwb.coop> On 05/23/2011 09:31 AM, Tony Hosking wrote: > An empty subrange gives a warning in the compiler. By my experiments, empty subrange, empty enumeration, and arrays thereof don't warn. > But, the semantics is that it is empty, and has no values of the type. > You cannot allocate (NEW) an empty type. > You cannot declare a field of empty type. It seems odd that we have this rule for fields, but no corresponding prohibition against arrays with empty element types. By experiments, cm3 allows this, for both fixed and open arrays, but treats such array types as empty types, something the language also does not say. At the least, the language and the compiler should agree with each other. Maybe records/objects and arrays should be treated consistently here? > Nor can you declare a variable of empty type. Again, oddly, there is no such prohibition in the language against declaring a formal parameter of empty type. Cm3 prohibits it, and calls it a 'variable' in the error message. Again, language and compiler should agree. The language also prohibits applying FIRST and LAST to the empty enumeration, but they are OK applied to an empty subrange. This makes sense, because they return values of the base type of the argument type, and such values exist for an empty subrange but not the empty enumeration, whose base type is only itself. > > On May 23, 2011, at 8:41 AM, Hendrik Boom wrote: > >> On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: >>> >>> Well, I can build the whole tree and see how many times it helps. >>> I think this is a pretty standard optimization technique. >>> Though it'd work better with compiler-derived additional information. >>> >>> I initially happened upon this idea developing test cases. >>> >>>> The code assumes the minimum of a type is less than or equal to its maximum. >>> >>> I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. >> >> What *is* the semantics of a range whose minimum is greater than its >> maximum? There plainly can't be any values in this range. How is a >> variable of this tyoe initialized? Not to some arbitrary value of the >> type, because there aren't any. I can see this type being useful to >> admit convenient generalizations -- for example, an array with n >> elements can still exist if n happens to be zero, but it seems to me >> that any code involving a value of the range for subscripts for this >> array must be simple unexecutable. >> >> Or is there some latitude available in the principle that a value of a >> variable must always be of the correct type? >> >> -- hendrik > > From hosking at cs.purdue.edu Mon May 23 18:54:36 2011 From: hosking at cs.purdue.edu (Tony Hosking) Date: Mon, 23 May 2011 12:54:36 -0400 Subject: [M3devel] range analysis? In-Reply-To: <4DDA8F1A.3070207@lcwb.coop> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> <4DDA8F1A.3070207@lcwb.coop> Message-ID: <8C9E1E77-686F-42E0-87FA-B573A4A02CC9@cs.purdue.edu> On May 23, 2011, at 12:45 PM, Rodney M. Bates wrote: > On 05/23/2011 09:31 AM, Tony Hosking wrote: >> An empty subrange gives a warning in the compiler. > > By my experiments, empty subrange, empty enumeration, and arrays > thereof don't warn. Sorry yes, you're right. But usage to declare any variable does. > >> But, the semantics is that it is empty, and has no values of the type. >> You cannot allocate (NEW) an empty type. >> You cannot declare a field of empty type. > > It seems odd that we have this rule for fields, but no corresponding > prohibition against arrays with empty element types. By experiments, > cm3 allows this, for both fixed and open arrays, but treats such array > types as empty types, something the language also does not say. > > At the least, the language and the compiler should agree with each other. > Maybe records/objects and arrays should be treated consistently here? Yes, I suppose so. >> Nor can you declare a variable of empty type. > > Again, oddly, there is no such prohibition in the language against > declaring a formal parameter of empty type. Cm3 prohibits it, > and calls it a 'variable' in the error message. You're right, though it's not the parameter that errors but the variable associated with the parameter. > Again, language and compiler should agree. Can you point me to the relevant entries in the language spec? > > The language also prohibits applying FIRST and LAST to the empty > enumeration, but they are OK applied to an empty subrange. > This makes sense, because they return values of the base type > of the argument type, and such values exist for an empty subrange > but not the empty enumeration, whose base type is only itself. > >> >> On May 23, 2011, at 8:41 AM, Hendrik Boom wrote: >> >>> On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: >>>> >>>> Well, I can build the whole tree and see how many times it helps. >>>> I think this is a pretty standard optimization technique. >>>> Though it'd work better with compiler-derived additional information. >>>> >>>> I initially happened upon this idea developing test cases. >>>> >>>>> The code assumes the minimum of a type is less than or equal to its maximum. >>>> >>>> I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. >>> >>> What *is* the semantics of a range whose minimum is greater than its >>> maximum? There plainly can't be any values in this range. How is a >>> variable of this tyoe initialized? Not to some arbitrary value of the >>> type, because there aren't any. I can see this type being useful to >>> admit convenient generalizations -- for example, an array with n >>> elements can still exist if n happens to be zero, but it seems to me >>> that any code involving a value of the range for subscripts for this >>> array must be simple unexecutable. >>> >>> Or is there some latitude available in the principle that a value of a >>> variable must always be of the correct type? >>> >>> -- hendrik >> >> From rodney_bates at lcwb.coop Mon May 23 20:26:52 2011 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Mon, 23 May 2011 13:26:52 -0500 Subject: [M3devel] range analysis? In-Reply-To: <8C9E1E77-686F-42E0-87FA-B573A4A02CC9@cs.purdue.edu> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> <4DDA8F1A.3070207@lcwb.coop> <8C9E1E77-686F-42E0-87FA-B573A4A02CC9@cs.purdue.edu> Message-ID: <4DDAA6EC.8060401@lcwb.coop> This needs more thought. On the one hand, 2.2.3 on array types allows the explicit element type in either kind of array type definition to be empty, unlike the way 2.2.4 on record types requires a field type to be nonempty. On the other hand, 2.2 has a general prohibition against declaring a variable of empty type, and it is all over the language spec that the elements of arrays are "variables". The general definition of variable in 2.1 would apply to array elements. Thre are numerous places that describe things that can be done with a variable that we all informally know can be done to an element, as it should be and we all have done many times. Moreover, 2.2.3 says in the first paragraph that the elements are variables. So here, the compiler is too liberal, and the language would be clearer with an explicit rule against empty element types. I haven't spotted anywhere a parameter is specifically called a variable, and it is not required to have a nonempty type in the description of parameter declarations. However, it certainly seems to me to fit the definition of variable, and as above, there are lots of things we know can be done with it that the language simply describes as doable to a variable. Moreover, for every mode, there is a rule that at call time, the formal is "bound to" a variable, which pretty well makes it variable in any context where it can be used. Even in a keyword binding, we are getting ready to bind it to a variable very soon. So maybe we need to 1) say a formal parameter is a variable, and 2) say the type in a parameter declaration must be nonempty. The language definition is also full of an ambiguity in its use of "variable" that I have been bothered by in talking about programming languages in general for years. One meaning is the meaning I have been talking about, The other is the kind of variable that is declared by a VAR declaration (not a VAR parameter). There are some uses in the language that I think need to have this latter meaning in order to be right. So we need a different or qualified term for this narrower meaning. On 05/23/2011 11:54 AM, Tony Hosking wrote: > > On May 23, 2011, at 12:45 PM, Rodney M. Bates wrote: > >> On 05/23/2011 09:31 AM, Tony Hosking wrote: >>> An empty subrange gives a warning in the compiler. >> >> By my experiments, empty subrange, empty enumeration, and arrays >> thereof don't warn. > > Sorry yes, you're right. But usage to declare any variable does. > >> >>> But, the semantics is that it is empty, and has no values of the type. >>> You cannot allocate (NEW) an empty type. >>> You cannot declare a field of empty type. >> >> It seems odd that we have this rule for fields, but no corresponding >> prohibition against arrays with empty element types. By experiments, >> cm3 allows this, for both fixed and open arrays, but treats such array >> types as empty types, something the language also does not say. >> >> At the least, the language and the compiler should agree with each other. >> Maybe records/objects and arrays should be treated consistently here? > > Yes, I suppose so. > >>> Nor can you declare a variable of empty type. >> >> Again, oddly, there is no such prohibition in the language against >> declaring a formal parameter of empty type. Cm3 prohibits it, >> and calls it a 'variable' in the error message. > > You're right, though it's not the parameter that errors but the variable associated with the parameter. > >> Again, language and compiler should agree. > > Can you point me to the relevant entries in the language spec? > >> >> The language also prohibits applying FIRST and LAST to the empty >> enumeration, but they are OK applied to an empty subrange. >> This makes sense, because they return values of the base type >> of the argument type, and such values exist for an empty subrange >> but not the empty enumeration, whose base type is only itself. >> >>> >>> On May 23, 2011, at 8:41 AM, Hendrik Boom wrote: >>> >>>> On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: >>>>> >>>>> Well, I can build the whole tree and see how many times it helps. >>>>> I think this is a pretty standard optimization technique. >>>>> Though it'd work better with compiler-derived additional information. >>>>> >>>>> I initially happened upon this idea developing test cases. >>>>> >>>>>> The code assumes the minimum of a type is less than or equal to its maximum. >>>>> >>>>> I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. >>>> >>>> What *is* the semantics of a range whose minimum is greater than its >>>> maximum? There plainly can't be any values in this range. How is a >>>> variable of this tyoe initialized? Not to some arbitrary value of the >>>> type, because there aren't any. I can see this type being useful to >>>> admit convenient generalizations -- for example, an array with n >>>> elements can still exist if n happens to be zero, but it seems to me >>>> that any code involving a value of the range for subscripts for this >>>> array must be simple unexecutable. >>>> >>>> Or is there some latitude available in the principle that a value of a >>>> variable must always be of the correct type? >>>> >>>> -- hendrik >>> >>> > > From hosking at cs.purdue.edu Mon May 23 20:45:37 2011 From: hosking at cs.purdue.edu (Tony Hosking) Date: Mon, 23 May 2011 14:45:37 -0400 Subject: [M3devel] range analysis? In-Reply-To: <4DDAA6EC.8060401@lcwb.coop> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> <4DDA8F1A.3070207@lcwb.coop> <8C9E1E77-686F-42E0-87FA-B573A4A02CC9@cs.purdue.edu> <4DDAA6EC.8060401@lcwb.coop> Message-ID: <45B5D160-9E80-4BB9-8411-F3976BCDC207@cs.purdue.edu> On May 23, 2011, at 2:26 PM, Rodney M. Bates wrote: > This needs more thought. On the one hand, 2.2.3 on array types allows > the explicit element type in either kind of array type definition to > be empty, unlike the way 2.2.4 on record types requires a field type > to be nonempty. I note that an array type of empty elements is itself empty and cannot be instantiated. > On the other hand, 2.2 has a general prohibition against declaring a > variable of empty type, and it is all over the language spec that the > elements of arrays are "variables". The general definition of variable > in 2.1 would apply to array elements. Thre are numerous places that > describe things that can be done with a variable that we all informally > know can be done to an element, as it should be and we all have done > many times. Moreover, 2.2.3 says in the first paragraph that the > elements are variables. So, it seems to me that we could simply disallow empty array elements and be within spec. > So here, the compiler is too liberal, and the language would be clearer > with an explicit rule against empty element types. Right. > I haven't spotted anywhere a parameter is specifically called a variable, > and it is not required to have a nonempty type in the description of > parameter declarations. However, it certainly seems to me to fit > the definition of variable, and as above, there are lots of things > we know can be done with it that the language simply describes as > doable to a variable. Moreover, for every mode, there is a rule > that at call time, the formal is "bound to" a variable, which pretty > well makes it variable in any context where it can be used. Even in > a keyword binding, we are getting ready to bind it to a variable > very soon. Right. > So maybe we need to 1) say a formal parameter is a variable, and A formal parameter is not in itself a variable. It's part of a type (the signature) not an implementation of that type. But every formal parameter has a corresponding variable in the body of the procedure that implements a given signature. > 2) say the type in a parameter declaration must be nonempty. This seems overwrought. I would stop simply at the variables (not the types) and let the binding of formal parameters to variables take care of the check as it currently does. > The language definition is also full of an ambiguity in its use > of "variable" that I have been bothered by in talking about programming > languages in general for years. One meaning is the meaning I have been > talking about, The other is the kind of variable that is declared by a > VAR declaration (not a VAR parameter). There are some uses in the > language that I think need to have this latter meaning in order to be right. Can you enumerate? > So we need a different or qualified term for this narrower meaning. > > On 05/23/2011 11:54 AM, Tony Hosking wrote: >> >> On May 23, 2011, at 12:45 PM, Rodney M. Bates wrote: >> >>> On 05/23/2011 09:31 AM, Tony Hosking wrote: >>>> An empty subrange gives a warning in the compiler. >>> >>> By my experiments, empty subrange, empty enumeration, and arrays >>> thereof don't warn. >> >> Sorry yes, you're right. But usage to declare any variable does. >> >>> >>>> But, the semantics is that it is empty, and has no values of the type. >>>> You cannot allocate (NEW) an empty type. >>>> You cannot declare a field of empty type. >>> >>> It seems odd that we have this rule for fields, but no corresponding >>> prohibition against arrays with empty element types. By experiments, >>> cm3 allows this, for both fixed and open arrays, but treats such array >>> types as empty types, something the language also does not say. >>> >>> At the least, the language and the compiler should agree with each other. >>> Maybe records/objects and arrays should be treated consistently here? >> >> Yes, I suppose so. >> >>>> Nor can you declare a variable of empty type. >>> >>> Again, oddly, there is no such prohibition in the language against >>> declaring a formal parameter of empty type. Cm3 prohibits it, >>> and calls it a 'variable' in the error message. >> >> You're right, though it's not the parameter that errors but the variable associated with the parameter. >> >>> Again, language and compiler should agree. >> >> Can you point me to the relevant entries in the language spec? >> >>> >>> The language also prohibits applying FIRST and LAST to the empty >>> enumeration, but they are OK applied to an empty subrange. >>> This makes sense, because they return values of the base type >>> of the argument type, and such values exist for an empty subrange >>> but not the empty enumeration, whose base type is only itself. >>> >>>> >>>> On May 23, 2011, at 8:41 AM, Hendrik Boom wrote: >>>> >>>>> On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: >>>>>> >>>>>> Well, I can build the whole tree and see how many times it helps. >>>>>> I think this is a pretty standard optimization technique. >>>>>> Though it'd work better with compiler-derived additional information. >>>>>> >>>>>> I initially happened upon this idea developing test cases. >>>>>> >>>>>>> The code assumes the minimum of a type is less than or equal to its maximum. >>>>>> >>>>>> I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. >>>>> >>>>> What *is* the semantics of a range whose minimum is greater than its >>>>> maximum? There plainly can't be any values in this range. How is a >>>>> variable of this tyoe initialized? Not to some arbitrary value of the >>>>> type, because there aren't any. I can see this type being useful to >>>>> admit convenient generalizations -- for example, an array with n >>>>> elements can still exist if n happens to be zero, but it seems to me >>>>> that any code involving a value of the range for subscripts for this >>>>> array must be simple unexecutable. >>>>> >>>>> Or is there some latitude available in the principle that a value of a >>>>> variable must always be of the correct type? >>>>> >>>>> -- hendrik >>>> >>>> >> >> From dabenavidesd at yahoo.es Mon May 23 22:44:11 2011 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Mon, 23 May 2011 21:44:11 +0100 (BST) Subject: [M3devel] range analysis? In-Reply-To: Message-ID: <346693.80219.qm@web29707.mail.ird.yahoo.com> Hi all: in one process it might be good to check for those optimization, but then you might want to abstract them all to allow to be pessimistic or to analyze them in ESC. This should require some good knowledge of the compiler though, which is maybe a harder task than just build a VCG but perhaps is too slow for m3cg, maybe for native backends, is more justifiable if so. Perhaps there is enough good trade off to do so. Thanks in advance --- El dom, 22/5/11, Jay K escribi?: De: Jay K Asunto: Re: [M3devel] range analysis? Para: "Tony" CC: "m3devel" Fecha: domingo, 22 de mayo, 2011 18:18 Well, I can build the whole tree and see how many times it helps. I think this is a pretty standard optimization technique. Though it'd work better with compiler-derived additional information. I initially happened upon this idea developing test cases. ?> The code assumes the minimum of a type is less than or equal to its maximum. I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. ?- Jay Subject: Re: range analysis? From: hosking at cs.purdue.edu Date: Sun, 22 May 2011 14:51:59 -0400 CC: m3devel at elegosoft.com To: jay.krell at cornell.edu So, one question is: what benefit does this really give? ?Your examples seem a little contrived. On May 22, 2011, at 4:26 AM, Jay K wrote: I've been sitting on this diff a long while. In some places the frontend knows the bounds of a type/value and will optimize away range checks. I'm pretty sure. This makes it do that more. I haven't looked at or tested this in ages. But the basic idea seems sound, simple, easy enough to get a few small wins from. For example if you have: a: [-10..-1]; b: [1..10]; then all comparisons between a and b are compile-time constant. Comparisons of cardinals to negative numbers, likewise. One thing maybe missing below is handling of empty ranges like a: [1..-1]; The code assumes the minimum of a type is less than or equal to its maximum. Index: m3-sys/m3front/src/misc/CG.i3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.i3,v retrieving revision 1.15 diff -r1.15 CG.i3 11c11 < IMPORT Target, M3CG, M3; --- > IMPORT Target, M3CG, M3, TInt; 402c402,406 < PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type); --- > PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type; >???????????????? min_valid: BOOLEAN := FALSE; >???????????????? max_valid: BOOLEAN := FALSE; >???????????????? min: Target.Int := TInt.Zero; >???????????????? max: Target.Int := TInt.Zero); 414,415c418,423 < PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0); < (* == Load (v, o, t.size, t.align, t) *) --- > PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0; >???????????????????? min_valid: BOOLEAN := FALSE; >???????????????????? max_valid: BOOLEAN := FALSE; >???????????????????? min: Target.Int := TInt.Zero; >???????????????????? max: Target.Int := TInt.Zero); > (* == Load (v, o, t.size, t.align, t, min/max...) *) Index: m3-sys/m3front/src/misc/CG.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.m3,v retrieving revision 1.40 diff -r1.40 CG.m3 13c13 < IMPORT M3, M3CG, M3CG_Ops, M3CG_Check; --- > IMPORT M3, M3CG, M3CG_Ops, M3CG_Check, RTIO, RTParams; 45a46,49 >???? min_valid : BOOLEAN := FALSE; (* whether or not min is valid *) >???? max_valid : BOOLEAN := FALSE; (* whether or not max is valid *) >???? min?????? : Target.Int := TInt.Zero; (* the minimum possible value *) >???? max?????? : Target.Int := TInt.Zero; (* the maximum possible value *) 80c84,85 < VAR --- > VAR >?? debug := FALSE; 604a610,614 >???? v.min?????? := TInt.Zero; >???? v.max?????? := TInt.Zero; >???? v.min_valid := FALSE; >???? v.max_valid := FALSE; >? 766a777,780 >???? x.min?????? := TInt.Zero; >???? x.max?????? := TInt.Zero; >???? x.min_valid := FALSE; >???? x.max_valid := FALSE; 978a993,995 >?????? IF debug THEN >???????? RTIO.PutText("m3front:cg:Init_int:NOT in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); >?????? END; 980a998,1001 >???? END; >? >???? IF debug THEN >?????? RTIO.PutText("m3front:cg:Init_int:in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); 1266c1287,1291 < PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type) = --- > PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type; >???????????????? min_valid: BOOLEAN := FALSE; >???????????????? max_valid: BOOLEAN := FALSE; >???????????????? min: Target.Int := TInt.Zero; >???????????????? max: Target.Int := TInt.Zero) = 1276c1301 ?????? SimpleLoad (v, o, t, min_valid, max_valid, min, max); 1291c1316 ???????? SimpleLoad (v, o, best_type, min_valid, max_valid, min, max); 1312c1337,1341 < PROCEDURE SimpleLoad (v: Var;? o: Offset;? t: Type) = --- > PROCEDURE SimpleLoad (v: Var;? o: Offset;? t: Type; >?????????????????????? min_valid: BOOLEAN := FALSE; >?????????????????????? max_valid: BOOLEAN := FALSE; >?????????????????????? min: Target.Int := TInt.Zero; >?????????????????????? max: Target.Int := TInt.Zero) = 1323a1353,1356 >?????? x.min_valid := min_valid; >?????? x.max_valid := max_valid; >?????? x.min?????? := min; >?????? x.max?????? := max; 1339a1373,1376 >?????? x.min?????? := TInt.Zero; >?????? x.max?????? := TInt.Zero; >?????? x.min_valid := FALSE; >?????? x.max_valid := FALSE; 1347a1385,1388 >???? stack[tos-1].min?????? := TInt.Zero; >???? stack[tos-1].max?????? := TInt.Zero; >???? stack[tos-1].min_valid := FALSE; >???? stack[tos-1].max_valid := FALSE; 1350c1391,1395 < PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0) = --- > PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0; >???????????????????? min_valid: BOOLEAN := FALSE; >???????????????????? max_valid: BOOLEAN := FALSE; >???????????????????? min: Target.Int := TInt.Zero; >???????????????????? max: Target.Int := TInt.Zero) = 1352c1397 ???? SimpleLoad (v, o, t, min_valid, max_valid, min, max); 1815a1861,1864 >?????? x.min_valid := TRUE; >?????? x.max_valid := TRUE; >?????? x.min := i; >?????? x.max := i; 1832,1834c1881,2007 ?? VAR always_true: BOOLEAN; >?????? always_false: BOOLEAN; >?????? left_type: Type; >?????? right_type: Type; >?????? left_min: Target.Int; >?????? left_max: Target.Int; >?????? right_min: Target.Int; >?????? right_max: Target.Int; >?????? left_signed: BOOLEAN; >?????? right_signed: BOOLEAN; >?? BEGIN >? >???? always_true := FALSE; >???? always_false := FALSE; >? >???? WITH left? = stack [SCheck (2, "Compare-left")], >????????? right = stack [SCheck (1, "Compare-right")] DO >? >?????? left_type := left.type; >?????? right_type := right.type; >? >?????? IF????? left.min_valid >?????????? AND left.max_valid >?????????? AND right.min_valid >?????????? AND right.max_valid >?????????? AND Target.OrdinalType[left_type] >?????????? AND Target.OrdinalType[right_type] THEN >? >???????? left_min := left.min; >???????? left_max := left.max; >???????? right_min := right.min; >???????? right_max := right.max; >???????? left_signed := Target.SignedType[left_type]; >???????? right_signed := Target.SignedType[right_type]; >? >???????? (* First handle types that match in signedness. *) >? >???????? IF left_signed = right_signed THEN >? >?????????? (* Check for ranges with no overlap. *) >? >?????????? IF left_signed (* and right_signed *) THEN >???????????? IF TInt.LT(left_max, right_min) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; >???????????? ELSIF TInt.GT(left_min, right_max) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; >???????????? END; >?????????? ELSE (* left_signed and right_signed both false *) >???????????? IF TWord.LT(left_max, right_min) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; >???????????? ELSIF TWord.GT(left_min, right_max) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; >???????????? END; >?????????? END; >? >?????????? (* Check for overlap just on the edge, e.g. [0..1] compared to [1..2]. *) >? >?????????? IF NOT (always_true OR always_false) THEN >???????????? IF TInt.EQ(left_max, right_min) THEN >?????????????? always_true := op = Cmp.LE; >?????????????? always_false := op = Cmp.GT; >???????????? ELSIF TInt.EQ(left_min, right_max) THEN >?????????????? always_true := op = Cmp.GE; >?????????????? always_false := op = Cmp.LT; >???????????? END; >?????????? END; >? >?????????? (* Handle equal subranges with one element, not likely to occur. *) >? >?????????? IF NOT (always_true OR always_false) THEN >???????????? IF????? TInt.EQ(left_max, left_min) >???????????????? AND TInt.EQ(left_max, right_max) >???????????????? AND TInt.EQ(left_max, right_min) THEN >?????????????? always_true? := op IN SET OF Cmp{Cmp.GE, Cmp.LE, Cmp.EQ}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.GT, Cmp.NE}; >???????????? END; >?????????? END; >???????? ELSE >? >?????????? (* Now deal with mixed up types (signed compared to unsigned). >??????????? * We may be able to merge these by setting some min/max >??????????? * to zero. That is, the minimum of an unsigned type is zero. >??????????? * However we want to be sure not to interpret unsigned min/max >??????????? * as signed. >??????????? *) >? >?????????? IF left_signed THEN >???????????? IF TInt.LT(left_max, TInt.Zero) THEN >?????????????? always_true? := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; >???????????? ELSIF TInt.EQ(left_max, TInt.Zero) THEN >?????????????? always_true? := op = Cmp.LE; >?????????????? always_false := op = Cmp.GT; >???????????? END; >?????????? ELSE (* right is signed *) >???????????? IF TInt.LT(right_max, TInt.Zero) THEN >?????????????? always_true? := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; >???????????? ELSIF TInt.EQ(right_max, TInt.Zero) THEN >?????????????? always_true := op = Cmp.GE; >?????????????? always_false := op = Cmp.LT; >???????????? END; >?????????? END; >???????? END; >?????? END; >?? >?????? <* ASSERT NOT (always_true AND always_false) *> >? >?????? IF always_true OR always_false THEN >???????? Discard(right_type); >???????? Discard(left_type); >???????? IF always_true THEN >?????????? cg.load_integer (Target.Integer.cg_type, TInt.One); >???????? ELSE >?????????? cg.load_integer (Target.Integer.cg_type, TInt.Zero); >???????? END >?????? ELSE >???????? IF Force_pair (commute := TRUE) THEN >?????????? op := M3CG.SwappedCompare [op]; >???????? END; >???????? cg.compare (t, Target.Integer.cg_type, op); >???????? SPop (2, "Compare"); >?????? END; 1836,1837d2008 ?????? x.min?????? := TInt.Zero; >?????? x.max?????? := TInt.Zero; >?????? x.min_valid := FALSE; >?????? x.max_valid := FALSE; 2977c3152,3153 < BEGIN --- > BEGIN >?? debug := debug OR RTParams.IsPresent ("m3front_cg_debug"); Index: m3-sys/m3front/src/values/Variable.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/values/Variable.m3,v retrieving revision 1.13 diff -r1.13 Variable.m3 362a363,365 >?? VAR min: Target.Int; >?????? max: Target.Int; >?????? bounds_valid: BOOLEAN; 395c398,401 ???????? (*GetBounds (t, min, max); >???????? bounds_valid := TInt.LE(min, max);*) >???????? bounds_valid := t.tipe # NIL AND Type.GetBounds(t.tipe, min, max) AND TInt.LE(min, max); >???????? CG.Load (t.cg_var, t.offset, t.size, t.cg_align, t.stk_type, bounds_valid, bounds_valid, min, max); -------------- next part -------------- An HTML attachment was scrubbed... URL: From hendrik at topoi.pooq.com Tue May 24 00:53:02 2011 From: hendrik at topoi.pooq.com (Hendrik Boom) Date: Mon, 23 May 2011 18:53:02 -0400 Subject: [M3devel] range analysis? In-Reply-To: <4DDAA6EC.8060401@lcwb.coop> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> <4DDA8F1A.3070207@lcwb.coop> <8C9E1E77-686F-42E0-87FA-B573A4A02CC9@cs.purdue.edu> <4DDAA6EC.8060401@lcwb.coop> Message-ID: <20110523225302.GA8980@topoi.pooq.com> On Mon, May 23, 2011 at 01:26:52PM -0500, Rodney M. Bates wrote: > This needs more thought. On the one hand, 2.2.3 on array types allows > the explicit element type in either kind of array type definition to > be empty, Well, the array might be empty, in which case no nonexistent values would be required when the array is created. > unlike the way 2.2.4 on record types requires a field type > to be nonempty. > > On the other hand, 2.2 has a general prohibition against declaring a > variable of empty type, and it is all over the language spec that the > elements of arrays are "variables". The general definition of variable > in 2.1 would apply to array elements. Thre are numerous places that > describe things that can be done with a variable that we all informally > know can be done to an element, as it should be and we all have done > many times. Moreover, 2.2.3 says in the first paragraph that the > elements are variables. > > So here, the compiler is too liberal, and the language would be clearer > with an explicit rule against empty element types. > > I haven't spotted anywhere a parameter is specifically called a variable, > and it is not required to have a nonempty type in the description of > parameter declarations. However, it certainly seems to me to fit > the definition of variable, and as above, there are lots of things > we know can be done with it that the language simply describes as > doable to a variable. Moreover, for every mode, there is a rule > that at call time, the formal is "bound to" a variable, which pretty > well makes it variable in any context where it can be used. Even in > a keyword binding, we are getting ready to bind it to a variable > very soon. > > So maybe we need to 1) say a formal parameter is a variable, and > 2) say the type in a parameter declaration must be nonempty. > > The language definition is also full of an ambiguity in its use > of "variable" that I have been bothered by in talking about programming > languages in general for years. One meaning is the meaning I have been > talking about, The other is the kind of variable that is declared by a > VAR declaration (not a VAR parameter). There are some uses in the > language that I think need to have this latter meaning in order to be right. > > So we need a different or qualified term for this narrower meaning. > > On 05/23/2011 11:54 AM, Tony Hosking wrote: >> >> On May 23, 2011, at 12:45 PM, Rodney M. Bates wrote: >> >>> On 05/23/2011 09:31 AM, Tony Hosking wrote: >>>> An empty subrange gives a warning in the compiler. >>> >>> By my experiments, empty subrange, empty enumeration, and arrays >>> thereof don't warn. >> >> Sorry yes, you're right. But usage to declare any variable does. >> >>> >>>> But, the semantics is that it is empty, and has no values of the type. >>>> You cannot allocate (NEW) an empty type. >>>> You cannot declare a field of empty type. >>> >>> It seems odd that we have this rule for fields, but no corresponding >>> prohibition against arrays with empty element types. By experiments, >>> cm3 allows this, for both fixed and open arrays, but treats such array >>> types as empty types, something the language also does not say. >>> >>> At the least, the language and the compiler should agree with each other. >>> Maybe records/objects and arrays should be treated consistently here? >> >> Yes, I suppose so. >> >>>> Nor can you declare a variable of empty type. >>> >>> Again, oddly, there is no such prohibition in the language against >>> declaring a formal parameter of empty type. Cm3 prohibits it, >>> and calls it a 'variable' in the error message. >> >> You're right, though it's not the parameter that errors but the variable associated with the parameter. >> >>> Again, language and compiler should agree. >> >> Can you point me to the relevant entries in the language spec? >> >>> >>> The language also prohibits applying FIRST and LAST to the empty >>> enumeration, but they are OK applied to an empty subrange. >>> This makes sense, because they return values of the base type >>> of the argument type, and such values exist for an empty subrange >>> but not the empty enumeration, whose base type is only itself. >>> >>>> >>>> On May 23, 2011, at 8:41 AM, Hendrik Boom wrote: >>>> >>>>> On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: >>>>>> >>>>>> Well, I can build the whole tree and see how many times it helps. >>>>>> I think this is a pretty standard optimization technique. >>>>>> Though it'd work better with compiler-derived additional information. >>>>>> >>>>>> I initially happened upon this idea developing test cases. >>>>>> >>>>>>> The code assumes the minimum of a type is less than or equal to its maximum. >>>>>> >>>>>> I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. >>>>> >>>>> What *is* the semantics of a range whose minimum is greater than its >>>>> maximum? There plainly can't be any values in this range. How is a >>>>> variable of this tyoe initialized? Not to some arbitrary value of the >>>>> type, because there aren't any. I can see this type being useful to >>>>> admit convenient generalizations -- for example, an array with n >>>>> elements can still exist if n happens to be zero, but it seems to me >>>>> that any code involving a value of the range for subscripts for this >>>>> array must be simple unexecutable. >>>>> >>>>> Or is there some latitude available in the principle that a value of a >>>>> variable must always be of the correct type? >>>>> >>>>> -- hendrik >>>> >>>> >> >> From hendrik at topoi.pooq.com Tue May 24 00:55:08 2011 From: hendrik at topoi.pooq.com (Hendrik Boom) Date: Mon, 23 May 2011 18:55:08 -0400 Subject: [M3devel] range analysis? In-Reply-To: <45B5D160-9E80-4BB9-8411-F3976BCDC207@cs.purdue.edu> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> <4DDA8F1A.3070207@lcwb.coop> <8C9E1E77-686F-42E0-87FA-B573A4A02CC9@cs.purdue.edu> <4DDAA6EC.8060401@lcwb.coop> <45B5D160-9E80-4BB9-8411-F3976BCDC207@cs.purdue.edu> Message-ID: <20110523225508.GB8980@topoi.pooq.com> On Mon, May 23, 2011 at 02:45:37PM -0400, Tony Hosking wrote: > > On May 23, 2011, at 2:26 PM, Rodney M. Bates wrote: > > > This needs more thought. On the one hand, 2.2.3 on array types allows > > the explicit element type in either kind of array type definition to > > be empty, unlike the way 2.2.4 on record types requires a field type > > to be nonempty. > > I note that an array type of empty elements is itself empty and cannot be instantiated. > > > On the other hand, 2.2 has a general prohibition against declaring a > > variable of empty type, and it is all over the language spec that the > > elements of arrays are "variables". The general definition of variable > > in 2.1 would apply to array elements. Thre are numerous places that > > describe things that can be done with a variable that we all informally > > know can be done to an element, as it should be and we all have done > > many times. Moreover, 2.2.3 says in the first paragraph that the > > elements are variables. > > So, it seems to me that we could simply disallow empty array elements and be within spec. You mean the array elements are empty? or that the element type is empty? These are very different concepts. From dabenavidesd at yahoo.es Tue May 24 00:54:33 2011 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Mon, 23 May 2011 23:54:33 +0100 (BST) Subject: [M3devel] range analysis? In-Reply-To: <346693.80219.qm@web29707.mail.ird.yahoo.com> Message-ID: <781156.80626.qm@web29716.mail.ird.yahoo.com> Hi all: an this could be even more payable in embedded architectures, of course there is always more work, but the market, is moving towards that I mean, people are *really* worried about lock-free data structures, etc, when there are tools that tackle that automatically or treat them formally and in Modula-3, see: http://www.eetimes.com/discussion/break-points/4027598/Executing-software-contracts I'm thinking in this more seriously, and by the amount of time they devised modula-3 end (1996 if I may say so), which is at least 10 years ahead of its common use and the tools they did as was their goal in DEC SRC, we are still on the front or struggling if so (and off-time of 5 years still have some room to speak up). And could be more if you think in separate efforts on it. As I heard from an old M3 friend, Obliq was? merely about to be the language standard for web and yet not one of them has the full technology of it as is (meaning it was the first agent language and it has type inference, and it's fast!). think in the Java JS binomial, for example and alike. I mean such an example, of usage and precedence in time is enough to say the quality in terms of the all package (Modula-3 and scripting language) Ok, it would be interesting to see why did they to take such decision (old friend's wish). Thanks in advance --- El lun, 23/5/11, Daniel Alejandro Benavides D. escribi?: De: Daniel Alejandro Benavides D. Asunto: Re: [M3devel] range analysis? Para: "Tony" , "Jay K" CC: "m3devel" Fecha: lunes, 23 de mayo, 2011 15:44 Hi all: in one process it might be good to check for those optimization, but then you might want to abstract them all to allow to be pessimistic or to analyze them in ESC. This should require some good knowledge of the compiler though, which is maybe a harder task than just build a VCG but perhaps is too slow for m3cg, maybe for native backends, is more justifiable if so. Perhaps there is enough good trade off to do so. Thanks in advance --- El dom, 22/5/11, Jay K escribi?: De: Jay K Asunto: Re: [M3devel] range analysis? Para: "Tony" CC: "m3devel" Fecha: domingo, 22 de mayo, 2011 18:18 Well, I can build the whole tree and see how many times it helps. I think this is a pretty standard optimization technique. Though it'd work better with compiler-derived additional information. I initially happened upon this idea developing test cases. ?> The code assumes the minimum of a type is less than or equal to its maximum. I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. ?- Jay Subject: Re: range analysis? From: hosking at cs.purdue.edu Date: Sun, 22 May 2011 14:51:59 -0400 CC: m3devel at elegosoft.com To: jay.krell at cornell.edu So, one question is: what benefit does this really give? ?Your examples seem a little contrived. On May 22, 2011, at 4:26 AM, Jay K wrote: I've been sitting on this diff a long while. In some places the frontend knows the bounds of a type/value and will optimize away range checks. I'm pretty sure. This makes it do that more. I haven't looked at or tested this in ages. But the basic idea seems sound, simple, easy enough to get a few small wins from. For example if you have: a: [-10..-1]; b: [1..10]; then all comparisons between a and b are compile-time constant. Comparisons of cardinals to negative numbers, likewise. One thing maybe missing below is handling of empty ranges like a: [1..-1]; The code assumes the minimum of a type is less than or equal to its maximum. Index: m3-sys/m3front/src/misc/CG.i3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.i3,v retrieving revision 1.15 diff -r1.15 CG.i3 11c11 < IMPORT Target, M3CG, M3; --- > IMPORT Target, M3CG, M3, TInt; 402c402,406 < PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type); --- > PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type; >???????????????? min_valid: BOOLEAN := FALSE; >???????????????? max_valid: BOOLEAN := FALSE; >???????????????? min: Target.Int := TInt.Zero; >???????????????? max: Target.Int := TInt.Zero); 414,415c418,423 < PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0); < (* == Load (v, o, t.size, t.align, t) *) --- > PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0; >???????????????????? min_valid: BOOLEAN := FALSE; >???????????????????? max_valid: BOOLEAN := FALSE; >???????????????????? min: Target.Int := TInt.Zero; >???????????????????? max: Target.Int := TInt.Zero); > (* == Load (v, o, t.size, t.align, t, min/max...) *) Index: m3-sys/m3front/src/misc/CG.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.m3,v retrieving revision 1.40 diff -r1.40 CG.m3 13c13 < IMPORT M3, M3CG, M3CG_Ops, M3CG_Check; --- > IMPORT M3, M3CG, M3CG_Ops, M3CG_Check, RTIO, RTParams; 45a46,49 >???? min_valid : BOOLEAN := FALSE; (* whether or not min is valid *) >???? max_valid : BOOLEAN := FALSE; (* whether or not max is valid *) >???? min?????? : Target.Int := TInt.Zero; (* the minimum possible value *) >???? max?????? : Target.Int := TInt.Zero; (* the maximum possible value *) 80c84,85 < VAR --- > VAR >?? debug := FALSE; 604a610,614 >???? v.min?????? := TInt.Zero; >???? v.max?????? := TInt.Zero; >???? v.min_valid := FALSE; >???? v.max_valid := FALSE; >? 766a777,780 >???? x.min?????? := TInt.Zero; >???? x.max?????? := TInt.Zero; >???? x.min_valid := FALSE; >???? x.max_valid := FALSE; 978a993,995 >?????? IF debug THEN >???????? RTIO.PutText("m3front:cg:Init_int:NOT in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); >?????? END; 980a998,1001 >???? END; >? >???? IF debug THEN >?????? RTIO.PutText("m3front:cg:Init_int:in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); 1266c1287,1291 < PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type) = --- > PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type; >???????????????? min_valid: BOOLEAN := FALSE; >???????????????? max_valid: BOOLEAN := FALSE; >???????????????? min: Target.Int := TInt.Zero; >???????????????? max: Target.Int := TInt.Zero) = 1276c1301 ?????? SimpleLoad (v, o, t, min_valid, max_valid, min, max); 1291c1316 ???????? SimpleLoad (v, o, best_type, min_valid, max_valid, min, max); 1312c1337,1341 < PROCEDURE SimpleLoad (v: Var;? o: Offset;? t: Type) = --- > PROCEDURE SimpleLoad (v: Var;? o: Offset;? t: Type; >?????????????????????? min_valid: BOOLEAN := FALSE; >?????????????????????? max_valid: BOOLEAN := FALSE; >?????????????????????? min: Target.Int := TInt.Zero; >?????????????????????? max: Target.Int := TInt.Zero) = 1323a1353,1356 >?????? x.min_valid := min_valid; >?????? x.max_valid := max_valid; >?????? x.min?????? := min; >?????? x.max?????? := max; 1339a1373,1376 >?????? x.min?????? := TInt.Zero; >?????? x.max?????? := TInt.Zero; >?????? x.min_valid := FALSE; >?????? x.max_valid := FALSE; 1347a1385,1388 >???? stack[tos-1].min?????? := TInt.Zero; >???? stack[tos-1].max?????? := TInt.Zero; >???? stack[tos-1].min_valid := FALSE; >???? stack[tos-1].max_valid := FALSE; 1350c1391,1395 < PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0) = --- > PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0; >???????????????????? min_valid: BOOLEAN := FALSE; >???????????????????? max_valid: BOOLEAN := FALSE; >???????????????????? min: Target.Int := TInt.Zero; >???????????????????? max: Target.Int := TInt.Zero) = 1352c1397 ???? SimpleLoad (v, o, t, min_valid, max_valid, min, max); 1815a1861,1864 >?????? x.min_valid := TRUE; >?????? x.max_valid := TRUE; >?????? x.min := i; >?????? x.max := i; 1832,1834c1881,2007 ?? VAR always_true: BOOLEAN; >?????? always_false: BOOLEAN; >?????? left_type: Type; >?????? right_type: Type; >?????? left_min: Target.Int; >?????? left_max: Target.Int; >?????? right_min: Target.Int; >?????? right_max: Target.Int; >?????? left_signed: BOOLEAN; >?????? right_signed: BOOLEAN; >?? BEGIN >? >???? always_true := FALSE; >???? always_false := FALSE; >? >???? WITH left? = stack [SCheck (2, "Compare-left")], >????????? right = stack [SCheck (1, "Compare-right")] DO >? >?????? left_type := left.type; >?????? right_type := right.type; >? >?????? IF????? left.min_valid >?????????? AND left.max_valid >?????????? AND right.min_valid >?????????? AND right.max_valid >?????????? AND Target.OrdinalType[left_type] >?????????? AND Target.OrdinalType[right_type] THEN >? >???????? left_min := left.min; >???????? left_max := left.max; >???????? right_min := right.min; >???????? right_max := right.max; >???????? left_signed := Target.SignedType[left_type]; >???????? right_signed := Target.SignedType[right_type]; >? >???????? (* First handle types that match in signedness. *) >? >???????? IF left_signed = right_signed THEN >? >?????????? (* Check for ranges with no overlap. *) >? >?????????? IF left_signed (* and right_signed *) THEN >???????????? IF TInt.LT(left_max, right_min) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; >???????????? ELSIF TInt.GT(left_min, right_max) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; >???????????? END; >?????????? ELSE (* left_signed and right_signed both false *) >???????????? IF TWord.LT(left_max, right_min) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; >???????????? ELSIF TWord.GT(left_min, right_max) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; >???????????? END; >?????????? END; >? >?????????? (* Check for overlap just on the edge, e.g. [0..1] compared to [1..2]. *) >? >?????????? IF NOT (always_true OR always_false) THEN >???????????? IF TInt.EQ(left_max, right_min) THEN >?????????????? always_true := op = Cmp.LE; >?????????????? always_false := op = Cmp.GT; >???????????? ELSIF TInt.EQ(left_min, right_max) THEN >?????????????? always_true := op = Cmp.GE; >?????????????? always_false := op = Cmp.LT; >???????????? END; >?????????? END; >? >?????????? (* Handle equal subranges with one element, not likely to occur. *) >? >?????????? IF NOT (always_true OR always_false) THEN >???????????? IF????? TInt.EQ(left_max, left_min) >???????????????? AND TInt.EQ(left_max, right_max) >???????????????? AND TInt.EQ(left_max, right_min) THEN >?????????????? always_true? := op IN SET OF Cmp{Cmp.GE, Cmp.LE, Cmp.EQ}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.GT, Cmp.NE}; >???????????? END; >?????????? END; >???????? ELSE >? >?????????? (* Now deal with mixed up types (signed compared to unsigned). >??????????? * We may be able to merge these by setting some min/max >??????????? * to zero. That is, the minimum of an unsigned type is zero. >??????????? * However we want to be sure not to interpret unsigned min/max >??????????? * as signed. >??????????? *) >? >?????????? IF left_signed THEN >???????????? IF TInt.LT(left_max, TInt.Zero) THEN >?????????????? always_true? := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; >???????????? ELSIF TInt.EQ(left_max, TInt.Zero) THEN >?????????????? always_true? := op = Cmp.LE; >?????????????? always_false := op = Cmp.GT; >???????????? END; >?????????? ELSE (* right is signed *) >???????????? IF TInt.LT(right_max, TInt.Zero) THEN >?????????????? always_true? := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; >???????????? ELSIF TInt.EQ(right_max, TInt.Zero) THEN >?????????????? always_true := op = Cmp.GE; >?????????????? always_false := op = Cmp.LT; >???????????? END; >?????????? END; >???????? END; >?????? END; >?? >?????? <* ASSERT NOT (always_true AND always_false) *> >? >?????? IF always_true OR always_false THEN >???????? Discard(right_type); >???????? Discard(left_type); >???????? IF always_true THEN >?????????? cg.load_integer (Target.Integer.cg_type, TInt.One); >???????? ELSE >?????????? cg.load_integer (Target.Integer.cg_type, TInt.Zero); >???????? END >?????? ELSE >???????? IF Force_pair (commute := TRUE) THEN >?????????? op := M3CG.SwappedCompare [op]; >???????? END; >???????? cg.compare (t, Target.Integer.cg_type, op); >???????? SPop (2, "Compare"); >?????? END; 1836,1837d2008 ?????? x.min?????? := TInt.Zero; >?????? x.max?????? := TInt.Zero; >?????? x.min_valid := FALSE; >?????? x.max_valid := FALSE; 2977c3152,3153 < BEGIN --- > BEGIN >?? debug := debug OR RTParams.IsPresent ("m3front_cg_debug"); Index: m3-sys/m3front/src/values/Variable.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/values/Variable.m3,v retrieving revision 1.13 diff -r1.13 Variable.m3 362a363,365 >?? VAR min: Target.Int; >?????? max: Target.Int; >?????? bounds_valid: BOOLEAN; 395c398,401 ???????? (*GetBounds (t, min, max); >???????? bounds_valid := TInt.LE(min, max);*) >???????? bounds_valid := t.tipe # NIL AND Type.GetBounds(t.tipe, min, max) AND TInt.LE(min, max); >???????? CG.Load (t.cg_var, t.offset, t.size, t.cg_align, t.stk_type, bounds_valid, bounds_valid, min, max); -------------- next part -------------- An HTML attachment was scrubbed... URL: From dabenavidesd at yahoo.es Tue May 24 01:22:51 2011 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Tue, 24 May 2011 00:22:51 +0100 (BST) Subject: [M3devel] range analysis? In-Reply-To: <781156.80626.qm@web29716.mail.ird.yahoo.com> Message-ID: <970550.60419.qm@web29711.mail.ird.yahoo.com> Hi all: and even more I can tell you there is plenty of teaching material on Object Oriented software construction in Modula-3 for Meyer's book,? then what about pulishing it and rewriting it in scripts of Obliq, which is harder to learn from 0, I guess Modula-3, but even if we facilitate that, what else is missing here (mentor, zeus3D, Obliq3D examples). See the same mentioned linked page. About Second comment on that page, I guess they talk about Model driven checking, from which there are tools that do that and are open source if they are so much we could adapt them to it. See Spec language. Thanks in advance --- El lun, 23/5/11, Daniel Alejandro Benavides D. escribi?: De: Daniel Alejandro Benavides D. Asunto: Re: [M3devel] range analysis? Para: "Tony" , "Jay K" CC: "m3devel" Fecha: lunes, 23 de mayo, 2011 17:54 Hi all: an this could be even more payable in embedded architectures, of course there is always more work, but the market, is moving towards that I mean, people are *really* worried about lock-free data structures, etc, when there are tools that tackle that automatically or treat them formally and in Modula-3, see: http://www.eetimes.com/discussion/break-points/4027598/Executing-software-contracts I'm thinking in this more seriously, and by the amount of time they devised modula-3 end (1996 if I may say so), which is at least 10 years ahead of its common use and the tools they did as was their goal in DEC SRC, we are still on the front or struggling if so (and off-time of 5 years still have some room to speak up). And could be more if you think in separate efforts on it. As I heard from an old M3 friend, Obliq was? merely about to be the language standard for web and yet not one of them has the full technology of it as is (meaning it was the first agent language and it has type inference, and it's fast!). think in the Java JS binomial, for example and alike. I mean such an example, of usage and precedence in time is enough to say the quality in terms of the all package (Modula-3 and scripting language) Ok, it would be interesting to see why did they to take such decision (old friend's wish). Thanks in advance --- El lun, 23/5/11, Daniel Alejandro Benavides D. escribi?: De: Daniel Alejandro Benavides D. Asunto: Re: [M3devel] range analysis? Para: "Tony" , "Jay K" CC: "m3devel" Fecha: lunes, 23 de mayo, 2011 15:44 Hi all: in one process it might be good to check for those optimization, but then you might want to abstract them all to allow to be pessimistic or to analyze them in ESC. This should require some good knowledge of the compiler though, which is maybe a harder task than just build a VCG but perhaps is too slow for m3cg, maybe for native backends, is more justifiable if so. Perhaps there is enough good trade off to do so. Thanks in advance --- El dom, 22/5/11, Jay K escribi?: De: Jay K Asunto: Re: [M3devel] range analysis? Para: "Tony" CC: "m3devel" Fecha: domingo, 22 de mayo, 2011 18:18 Well, I can build the whole tree and see how many times it helps. I think this is a pretty standard optimization technique. Though it'd work better with compiler-derived additional information. I initially happened upon this idea developing test cases. ?> The code assumes the minimum of a type is less than or equal to its maximum. I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. ?- Jay Subject: Re: range analysis? From: hosking at cs.purdue.edu Date: Sun, 22 May 2011 14:51:59 -0400 CC: m3devel at elegosoft.com To: jay.krell at cornell.edu So, one question is: what benefit does this really give? ?Your examples seem a little contrived. On May 22, 2011, at 4:26 AM, Jay K wrote: I've been sitting on this diff a long while. In some places the frontend knows the bounds of a type/value and will optimize away range checks. I'm pretty sure. This makes it do that more. I haven't looked at or tested this in ages. But the basic idea seems sound, simple, easy enough to get a few small wins from. For example if you have: a: [-10..-1]; b: [1..10]; then all comparisons between a and b are compile-time constant. Comparisons of cardinals to negative numbers, likewise. One thing maybe missing below is handling of empty ranges like a: [1..-1]; The code assumes the minimum of a type is less than or equal to its maximum. Index: m3-sys/m3front/src/misc/CG.i3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.i3,v retrieving revision 1.15 diff -r1.15 CG.i3 11c11 < IMPORT Target, M3CG, M3; --- > IMPORT Target, M3CG, M3, TInt; 402c402,406 < PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type); --- > PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type; >???????????????? min_valid: BOOLEAN := FALSE; >???????????????? max_valid: BOOLEAN := FALSE; >???????????????? min: Target.Int := TInt.Zero; >???????????????? max: Target.Int := TInt.Zero); 414,415c418,423 < PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0); < (* == Load (v, o, t.size, t.align, t) *) --- > PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0; >???????????????????? min_valid: BOOLEAN := FALSE; >???????????????????? max_valid: BOOLEAN := FALSE; >???????????????????? min: Target.Int := TInt.Zero; >???????????????????? max: Target.Int := TInt.Zero); > (* == Load (v, o, t.size, t.align, t, min/max...) *) Index: m3-sys/m3front/src/misc/CG.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.m3,v retrieving revision 1.40 diff -r1.40 CG.m3 13c13 < IMPORT M3, M3CG, M3CG_Ops, M3CG_Check; --- > IMPORT M3, M3CG, M3CG_Ops, M3CG_Check, RTIO, RTParams; 45a46,49 >???? min_valid : BOOLEAN := FALSE; (* whether or not min is valid *) >???? max_valid : BOOLEAN := FALSE; (* whether or not max is valid *) >???? min?????? : Target.Int := TInt.Zero; (* the minimum possible value *) >???? max?????? : Target.Int := TInt.Zero; (* the maximum possible value *) 80c84,85 < VAR --- > VAR >?? debug := FALSE; 604a610,614 >???? v.min?????? := TInt.Zero; >???? v.max?????? := TInt.Zero; >???? v.min_valid := FALSE; >???? v.max_valid := FALSE; >? 766a777,780 >???? x.min?????? := TInt.Zero; >???? x.max?????? := TInt.Zero; >???? x.min_valid := FALSE; >???? x.max_valid := FALSE; 978a993,995 >?????? IF debug THEN >???????? RTIO.PutText("m3front:cg:Init_int:NOT in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); >?????? END; 980a998,1001 >???? END; >? >???? IF debug THEN >?????? RTIO.PutText("m3front:cg:Init_int:in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); 1266c1287,1291 < PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type) = --- > PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type; >???????????????? min_valid: BOOLEAN := FALSE; >???????????????? max_valid: BOOLEAN := FALSE; >???????????????? min: Target.Int := TInt.Zero; >???????????????? max: Target.Int := TInt.Zero) = 1276c1301 ?????? SimpleLoad (v, o, t, min_valid, max_valid, min, max); 1291c1316 ???????? SimpleLoad (v, o, best_type, min_valid, max_valid, min, max); 1312c1337,1341 < PROCEDURE SimpleLoad (v: Var;? o: Offset;? t: Type) = --- > PROCEDURE SimpleLoad (v: Var;? o: Offset;? t: Type; >?????????????????????? min_valid: BOOLEAN := FALSE; >?????????????????????? max_valid: BOOLEAN := FALSE; >?????????????????????? min: Target.Int := TInt.Zero; >?????????????????????? max: Target.Int := TInt.Zero) = 1323a1353,1356 >?????? x.min_valid := min_valid; >?????? x.max_valid := max_valid; >?????? x.min?????? := min; >?????? x.max?????? := max; 1339a1373,1376 >?????? x.min?????? := TInt.Zero; >?????? x.max?????? := TInt.Zero; >?????? x.min_valid := FALSE; >?????? x.max_valid := FALSE; 1347a1385,1388 >???? stack[tos-1].min?????? := TInt.Zero; >???? stack[tos-1].max?????? := TInt.Zero; >???? stack[tos-1].min_valid := FALSE; >???? stack[tos-1].max_valid := FALSE; 1350c1391,1395 < PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0) = --- > PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0; >???????????????????? min_valid: BOOLEAN := FALSE; >???????????????????? max_valid: BOOLEAN := FALSE; >???????????????????? min: Target.Int := TInt.Zero; >???????????????????? max: Target.Int := TInt.Zero) = 1352c1397 ???? SimpleLoad (v, o, t, min_valid, max_valid, min, max); 1815a1861,1864 >?????? x.min_valid := TRUE; >?????? x.max_valid := TRUE; >?????? x.min := i; >?????? x.max := i; 1832,1834c1881,2007 ?? VAR always_true: BOOLEAN; >?????? always_false: BOOLEAN; >?????? left_type: Type; >?????? right_type: Type; >?????? left_min: Target.Int; >?????? left_max: Target.Int; >?????? right_min: Target.Int; >?????? right_max: Target.Int; >?????? left_signed: BOOLEAN; >?????? right_signed: BOOLEAN; >?? BEGIN >? >???? always_true := FALSE; >???? always_false := FALSE; >? >???? WITH left? = stack [SCheck (2, "Compare-left")], >????????? right = stack [SCheck (1, "Compare-right")] DO >? >?????? left_type := left.type; >?????? right_type := right.type; >? >?????? IF????? left.min_valid >?????????? AND left.max_valid >?????????? AND right.min_valid >?????????? AND right.max_valid >?????????? AND Target.OrdinalType[left_type] >?????????? AND Target.OrdinalType[right_type] THEN >? >???????? left_min := left.min; >???????? left_max := left.max; >???????? right_min := right.min; >???????? right_max := right.max; >???????? left_signed := Target.SignedType[left_type]; >???????? right_signed := Target.SignedType[right_type]; >? >???????? (* First handle types that match in signedness. *) >? >???????? IF left_signed = right_signed THEN >? >?????????? (* Check for ranges with no overlap. *) >? >?????????? IF left_signed (* and right_signed *) THEN >???????????? IF TInt.LT(left_max, right_min) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; >???????????? ELSIF TInt.GT(left_min, right_max) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; >???????????? END; >?????????? ELSE (* left_signed and right_signed both false *) >???????????? IF TWord.LT(left_max, right_min) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; >???????????? ELSIF TWord.GT(left_min, right_max) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; >???????????? END; >?????????? END; >? >?????????? (* Check for overlap just on the edge, e.g. [0..1] compared to [1..2]. *) >? >?????????? IF NOT (always_true OR always_false) THEN >???????????? IF TInt.EQ(left_max, right_min) THEN >?????????????? always_true := op = Cmp.LE; >?????????????? always_false := op = Cmp.GT; >???????????? ELSIF TInt.EQ(left_min, right_max) THEN >?????????????? always_true := op = Cmp.GE; >?????????????? always_false := op = Cmp.LT; >???????????? END; >?????????? END; >? >?????????? (* Handle equal subranges with one element, not likely to occur. *) >? >?????????? IF NOT (always_true OR always_false) THEN >???????????? IF????? TInt.EQ(left_max, left_min) >???????????????? AND TInt.EQ(left_max, right_max) >???????????????? AND TInt.EQ(left_max, right_min) THEN >?????????????? always_true? := op IN SET OF Cmp{Cmp.GE, Cmp.LE, Cmp.EQ}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.GT, Cmp.NE}; >???????????? END; >?????????? END; >???????? ELSE >? >?????????? (* Now deal with mixed up types (signed compared to unsigned). >??????????? * We may be able to merge these by setting some min/max >??????????? * to zero. That is, the minimum of an unsigned type is zero. >??????????? * However we want to be sure not to interpret unsigned min/max >??????????? * as signed. >??????????? *) >? >?????????? IF left_signed THEN >???????????? IF TInt.LT(left_max, TInt.Zero) THEN >?????????????? always_true? := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; >???????????? ELSIF TInt.EQ(left_max, TInt.Zero) THEN >?????????????? always_true? := op = Cmp.LE; >?????????????? always_false := op = Cmp.GT; >???????????? END; >?????????? ELSE (* right is signed *) >???????????? IF TInt.LT(right_max, TInt.Zero) THEN >?????????????? always_true? := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; >???????????? ELSIF TInt.EQ(right_max, TInt.Zero) THEN >?????????????? always_true := op = Cmp.GE; >?????????????? always_false := op = Cmp.LT; >???????????? END; >?????????? END; >???????? END; >?????? END; >?? >?????? <* ASSERT NOT (always_true AND always_false) *> >? >?????? IF always_true OR always_false THEN >???????? Discard(right_type); >???????? Discard(left_type); >???????? IF always_true THEN >?????????? cg.load_integer (Target.Integer.cg_type, TInt.One); >???????? ELSE >?????????? cg.load_integer (Target.Integer.cg_type, TInt.Zero); >???????? END >?????? ELSE >???????? IF Force_pair (commute := TRUE) THEN >?????????? op := M3CG.SwappedCompare [op]; >???????? END; >???????? cg.compare (t, Target.Integer.cg_type, op); >???????? SPop (2, "Compare"); >?????? END; 1836,1837d2008 ?????? x.min?????? := TInt.Zero; >?????? x.max?????? := TInt.Zero; >?????? x.min_valid := FALSE; >?????? x.max_valid := FALSE; 2977c3152,3153 < BEGIN --- > BEGIN >?? debug := debug OR RTParams.IsPresent ("m3front_cg_debug"); Index: m3-sys/m3front/src/values/Variable.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/values/Variable.m3,v retrieving revision 1.13 diff -r1.13 Variable.m3 362a363,365 >?? VAR min: Target.Int; >?????? max: Target.Int; >?????? bounds_valid: BOOLEAN; 395c398,401 ???????? (*GetBounds (t, min, max); >???????? bounds_valid := TInt.LE(min, max);*) >???????? bounds_valid := t.tipe # NIL AND Type.GetBounds(t.tipe, min, max) AND TInt.LE(min, max); >???????? CG.Load (t.cg_var, t.offset, t.size, t.cg_align, t.stk_type, bounds_valid, bounds_valid, min, max); -------------- next part -------------- An HTML attachment was scrubbed... URL: From rodney_bates at lcwb.coop Tue May 24 02:16:18 2011 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Mon, 23 May 2011 19:16:18 -0500 Subject: [M3devel] range analysis? In-Reply-To: <20110523225302.GA8980@topoi.pooq.com> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> <4DDA8F1A.3070207@lcwb.coop> <8C9E1E77-686F-42E0-87FA-B573A4A02CC9@cs.purdue.edu> <4DDAA6EC.8060401@lcwb.coop> <20110523225302.GA8980@topoi.pooq.com> Message-ID: <4DDAF8D2.2090800@lcwb.coop> On 05/23/2011 05:53 PM, Hendrik Boom wrote: > On Mon, May 23, 2011 at 01:26:52PM -0500, Rodney M. Bates wrote: >> This needs more thought. On the one hand, 2.2.3 on array types allows >> the explicit element type in either kind of array type definition to >> be empty, > > Well, the array might be empty, in which case no nonexistent values > would be required when the array is created. Good point. Right now, the compiler does not allow creation of such arrays, either fixed or open. The error messages both refer to the _array type_ whose elements also have empty type as an "empty type", regardless of whether the element count is zero or positive. > >> unlike the way 2.2.4 on record types requires a field type >> to be nonempty. >> >> On the other hand, 2.2 has a general prohibition against declaring a >> variable of empty type, and it is all over the language spec that the >> elements of arrays are "variables". The general definition of variable >> in 2.1 would apply to array elements. Thre are numerous places that >> describe things that can be done with a variable that we all informally >> know can be done to an element, as it should be and we all have done >> many times. Moreover, 2.2.3 says in the first paragraph that the >> elements are variables. >> >> So here, the compiler is too liberal, and the language would be clearer >> with an explicit rule against empty element types. >> >> I haven't spotted anywhere a parameter is specifically called a variable, >> and it is not required to have a nonempty type in the description of >> parameter declarations. However, it certainly seems to me to fit >> the definition of variable, and as above, there are lots of things >> we know can be done with it that the language simply describes as >> doable to a variable. Moreover, for every mode, there is a rule >> that at call time, the formal is "bound to" a variable, which pretty >> well makes it variable in any context where it can be used. Even in >> a keyword binding, we are getting ready to bind it to a variable >> very soon. >> >> So maybe we need to 1) say a formal parameter is a variable, and >> 2) say the type in a parameter declaration must be nonempty. >> >> The language definition is also full of an ambiguity in its use >> of "variable" that I have been bothered by in talking about programming >> languages in general for years. One meaning is the meaning I have been >> talking about, The other is the kind of variable that is declared by a >> VAR declaration (not a VAR parameter). There are some uses in the >> language that I think need to have this latter meaning in order to be right. >> >> So we need a different or qualified term for this narrower meaning. >> >> On 05/23/2011 11:54 AM, Tony Hosking wrote: >>> >>> On May 23, 2011, at 12:45 PM, Rodney M. Bates wrote: >>> >>>> On 05/23/2011 09:31 AM, Tony Hosking wrote: >>>>> An empty subrange gives a warning in the compiler. >>>> >>>> By my experiments, empty subrange, empty enumeration, and arrays >>>> thereof don't warn. >>> >>> Sorry yes, you're right. But usage to declare any variable does. >>> >>>> >>>>> But, the semantics is that it is empty, and has no values of the type. >>>>> You cannot allocate (NEW) an empty type. >>>>> You cannot declare a field of empty type. >>>> >>>> It seems odd that we have this rule for fields, but no corresponding >>>> prohibition against arrays with empty element types. By experiments, >>>> cm3 allows this, for both fixed and open arrays, but treats such array >>>> types as empty types, something the language also does not say. >>>> >>>> At the least, the language and the compiler should agree with each other. >>>> Maybe records/objects and arrays should be treated consistently here? >>> >>> Yes, I suppose so. >>> >>>>> Nor can you declare a variable of empty type. >>>> >>>> Again, oddly, there is no such prohibition in the language against >>>> declaring a formal parameter of empty type. Cm3 prohibits it, >>>> and calls it a 'variable' in the error message. >>> >>> You're right, though it's not the parameter that errors but the variable associated with the parameter. >>> >>>> Again, language and compiler should agree. >>> >>> Can you point me to the relevant entries in the language spec? >>> >>>> >>>> The language also prohibits applying FIRST and LAST to the empty >>>> enumeration, but they are OK applied to an empty subrange. >>>> This makes sense, because they return values of the base type >>>> of the argument type, and such values exist for an empty subrange >>>> but not the empty enumeration, whose base type is only itself. >>>> >>>>> >>>>> On May 23, 2011, at 8:41 AM, Hendrik Boom wrote: >>>>> >>>>>> On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: >>>>>>> >>>>>>> Well, I can build the whole tree and see how many times it helps. >>>>>>> I think this is a pretty standard optimization technique. >>>>>>> Though it'd work better with compiler-derived additional information. >>>>>>> >>>>>>> I initially happened upon this idea developing test cases. >>>>>>> >>>>>>>> The code assumes the minimum of a type is less than or equal to its maximum. >>>>>>> >>>>>>> I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. >>>>>> >>>>>> What *is* the semantics of a range whose minimum is greater than its >>>>>> maximum? There plainly can't be any values in this range. How is a >>>>>> variable of this tyoe initialized? Not to some arbitrary value of the >>>>>> type, because there aren't any. I can see this type being useful to >>>>>> admit convenient generalizations -- for example, an array with n >>>>>> elements can still exist if n happens to be zero, but it seems to me >>>>>> that any code involving a value of the range for subscripts for this >>>>>> array must be simple unexecutable. >>>>>> >>>>>> Or is there some latitude available in the principle that a value of a >>>>>> variable must always be of the correct type? >>>>>> >>>>>> -- hendrik >>>>> >>>>> >>> >>> > From hosking at cs.purdue.edu Tue May 24 04:04:18 2011 From: hosking at cs.purdue.edu (Tony Hosking) Date: Mon, 23 May 2011 22:04:18 -0400 Subject: [M3devel] range analysis? In-Reply-To: <20110523225302.GA8980@topoi.pooq.com> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> <4DDA8F1A.3070207@lcwb.coop> <8C9E1E77-686F-42E0-87FA-B573A4A02CC9@cs.purdue.edu> <4DDAA6EC.8060401@lcwb.coop> <20110523225302.GA8980@topoi.pooq.com> Message-ID: On May 23, 2011, at 6:53 PM, Hendrik Boom wrote: > On Mon, May 23, 2011 at 01:26:52PM -0500, Rodney M. Bates wrote: >> This needs more thought. On the one hand, 2.2.3 on array types allows >> the explicit element type in either kind of array type definition to >> be empty, > > Well, the array might be empty, in which case no nonexistent values > would be required when the array is created. You cannot instantiate an empty array type. > >> unlike the way 2.2.4 on record types requires a field type >> to be nonempty. >> >> On the other hand, 2.2 has a general prohibition against declaring a >> variable of empty type, and it is all over the language spec that the >> elements of arrays are "variables". The general definition of variable >> in 2.1 would apply to array elements. Thre are numerous places that >> describe things that can be done with a variable that we all informally >> know can be done to an element, as it should be and we all have done >> many times. Moreover, 2.2.3 says in the first paragraph that the >> elements are variables. >> >> So here, the compiler is too liberal, and the language would be clearer >> with an explicit rule against empty element types. >> >> I haven't spotted anywhere a parameter is specifically called a variable, >> and it is not required to have a nonempty type in the description of >> parameter declarations. However, it certainly seems to me to fit >> the definition of variable, and as above, there are lots of things >> we know can be done with it that the language simply describes as >> doable to a variable. Moreover, for every mode, there is a rule >> that at call time, the formal is "bound to" a variable, which pretty >> well makes it variable in any context where it can be used. Even in >> a keyword binding, we are getting ready to bind it to a variable >> very soon. >> >> So maybe we need to 1) say a formal parameter is a variable, and >> 2) say the type in a parameter declaration must be nonempty. >> >> The language definition is also full of an ambiguity in its use >> of "variable" that I have been bothered by in talking about programming >> languages in general for years. One meaning is the meaning I have been >> talking about, The other is the kind of variable that is declared by a >> VAR declaration (not a VAR parameter). There are some uses in the >> language that I think need to have this latter meaning in order to be right. >> >> So we need a different or qualified term for this narrower meaning. >> >> On 05/23/2011 11:54 AM, Tony Hosking wrote: >>> >>> On May 23, 2011, at 12:45 PM, Rodney M. Bates wrote: >>> >>>> On 05/23/2011 09:31 AM, Tony Hosking wrote: >>>>> An empty subrange gives a warning in the compiler. >>>> >>>> By my experiments, empty subrange, empty enumeration, and arrays >>>> thereof don't warn. >>> >>> Sorry yes, you're right. But usage to declare any variable does. >>> >>>> >>>>> But, the semantics is that it is empty, and has no values of the type. >>>>> You cannot allocate (NEW) an empty type. >>>>> You cannot declare a field of empty type. >>>> >>>> It seems odd that we have this rule for fields, but no corresponding >>>> prohibition against arrays with empty element types. By experiments, >>>> cm3 allows this, for both fixed and open arrays, but treats such array >>>> types as empty types, something the language also does not say. >>>> >>>> At the least, the language and the compiler should agree with each other. >>>> Maybe records/objects and arrays should be treated consistently here? >>> >>> Yes, I suppose so. >>> >>>>> Nor can you declare a variable of empty type. >>>> >>>> Again, oddly, there is no such prohibition in the language against >>>> declaring a formal parameter of empty type. Cm3 prohibits it, >>>> and calls it a 'variable' in the error message. >>> >>> You're right, though it's not the parameter that errors but the variable associated with the parameter. >>> >>>> Again, language and compiler should agree. >>> >>> Can you point me to the relevant entries in the language spec? >>> >>>> >>>> The language also prohibits applying FIRST and LAST to the empty >>>> enumeration, but they are OK applied to an empty subrange. >>>> This makes sense, because they return values of the base type >>>> of the argument type, and such values exist for an empty subrange >>>> but not the empty enumeration, whose base type is only itself. >>>> >>>>> >>>>> On May 23, 2011, at 8:41 AM, Hendrik Boom wrote: >>>>> >>>>>> On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: >>>>>>> >>>>>>> Well, I can build the whole tree and see how many times it helps. >>>>>>> I think this is a pretty standard optimization technique. >>>>>>> Though it'd work better with compiler-derived additional information. >>>>>>> >>>>>>> I initially happened upon this idea developing test cases. >>>>>>> >>>>>>>> The code assumes the minimum of a type is less than or equal to its maximum. >>>>>>> >>>>>>> I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. >>>>>> >>>>>> What *is* the semantics of a range whose minimum is greater than its >>>>>> maximum? There plainly can't be any values in this range. How is a >>>>>> variable of this tyoe initialized? Not to some arbitrary value of the >>>>>> type, because there aren't any. I can see this type being useful to >>>>>> admit convenient generalizations -- for example, an array with n >>>>>> elements can still exist if n happens to be zero, but it seems to me >>>>>> that any code involving a value of the range for subscripts for this >>>>>> array must be simple unexecutable. >>>>>> >>>>>> Or is there some latitude available in the principle that a value of a >>>>>> variable must always be of the correct type? >>>>>> >>>>>> -- hendrik >>>>> >>>>> >>> >>> From hosking at cs.purdue.edu Tue May 24 04:04:40 2011 From: hosking at cs.purdue.edu (Tony Hosking) Date: Mon, 23 May 2011 22:04:40 -0400 Subject: [M3devel] range analysis? In-Reply-To: <20110523225508.GB8980@topoi.pooq.com> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> <4DDA8F1A.3070207@lcwb.coop> <8C9E1E77-686F-42E0-87FA-B573A4A02CC9@cs.purdue.edu> <4DDAA6EC.8060401@lcwb.coop> <45B5D160-9E80-4BB9-8411-F3976BCDC207@cs.purdue.edu> <20110523225508.GB8980@topoi.pooq.com> Message-ID: <67872FDF-2DF6-43D5-8CCD-F1E4644CA2A6@cs.purdue.edu> Element type. On May 23, 2011, at 6:55 PM, Hendrik Boom wrote: > On Mon, May 23, 2011 at 02:45:37PM -0400, Tony Hosking wrote: >> >> On May 23, 2011, at 2:26 PM, Rodney M. Bates wrote: >> >>> This needs more thought. On the one hand, 2.2.3 on array types allows >>> the explicit element type in either kind of array type definition to >>> be empty, unlike the way 2.2.4 on record types requires a field type >>> to be nonempty. >> >> I note that an array type of empty elements is itself empty and cannot be instantiated. >> >>> On the other hand, 2.2 has a general prohibition against declaring a >>> variable of empty type, and it is all over the language spec that the >>> elements of arrays are "variables". The general definition of variable >>> in 2.1 would apply to array elements. Thre are numerous places that >>> describe things that can be done with a variable that we all informally >>> know can be done to an element, as it should be and we all have done >>> many times. Moreover, 2.2.3 says in the first paragraph that the >>> elements are variables. >> >> So, it seems to me that we could simply disallow empty array elements and be within spec. > > You mean the array elements are empty? or that the element type is > empty? These are very different concepts. From hosking at cs.purdue.edu Tue May 24 04:06:34 2011 From: hosking at cs.purdue.edu (Tony Hosking) Date: Mon, 23 May 2011 22:06:34 -0400 Subject: [M3devel] range analysis? In-Reply-To: <4DDAF56D.8010505@lcwb.coop> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> <4DDA8F1A.3070207@lcwb.coop> <8C9E1E77-686F-42E0-87FA-B573A4A02CC9@cs.purdue.edu> <4DDAA6EC.8060401@lcwb.coop> <45B5D160-9E80-4BB9-8411-F3976BCDC207@cs.purdue.edu> <4DDAF56D.8010505@lcwb.coop> Message-ID: <919256C9-1773-43EC-9B62-C45883935957@cs.purdue.edu> Sorry for the terse response. Is there a proposal buried in there? On May 23, 2011, at 8:01 PM, Rodney M. Bates wrote: > > > On 05/23/2011 01:45 PM, Tony Hosking wrote: >> >> On May 23, 2011, at 2:26 PM, Rodney M. Bates wrote: >> >>> This needs more thought. On the one hand, 2.2.3 on array types allows >>> the explicit element type in either kind of array type definition to >>> be empty, unlike the way 2.2.4 on record types requires a field type >>> to be nonempty. >> >> I note that an array type of empty elements is itself empty and cannot be instantiated. >> > > Yes. > >>> On the other hand, 2.2 has a general prohibition against declaring a >>> variable of empty type, and it is all over the language spec that the >>> elements of arrays are "variables". The general definition of variable >>> in 2.1 would apply to array elements. Thre are numerous places that >>> describe things that can be done with a variable that we all informally >>> know can be done to an element, as it should be and we all have done >>> many times. Moreover, 2.2.3 says in the first paragraph that the >>> elements are variables. >> >> So, it seems to me that we could simply disallow empty array elements and be within spec. > > I agree. > >> >>> So here, the compiler is too liberal, and the language would be clearer >>> with an explicit rule against empty element types. >> >> Right. >> >>> I haven't spotted anywhere a parameter is specifically called a variable, >>> and it is not required to have a nonempty type in the description of >>> parameter declarations. However, it certainly seems to me to fit >>> the definition of variable, and as above, there are lots of things >>> we know can be done with it that the language simply describes as >>> doable to a variable. Moreover, for every mode, there is a rule >>> that at call time, the formal is "bound to" a variable, which pretty >>> well makes it variable in any context where it can be used. Even in >>> a keyword binding, we are getting ready to bind it to a variable >>> very soon. >> >> Right. >> >>> So maybe we need to 1) say a formal parameter is a variable, and >> >> A formal parameter is not in itself a variable. It's part of a type (the signature) not an implementation of that type. But every formal parameter has a corresponding variable in the body of the procedure that implements a given signature. >> >>> 2) say the type in a parameter declaration must be nonempty. >> >> This seems overwrought. I would stop simply at the variables (not the types) and let the binding of formal parameters to variables take care of the check as it currently does. >> > > My first thought was that this argument is no more or less applicable to > a procedure type containing a formal of empty type than to a record > type containing a field (which is currently defined as a variable) > of empty type. Both are just types constructed from other type(s), > to be maybe instantiated later. In the case of the record, we now > disallow the type to be constructed. Your proposal would inconsistently > allow the procedure type to be constructed but complain when an > attempt is made to instantiate it (i.e., call it) later. > > My second thought was that a procedure type with empty-typed formal > is not an empty type, because it contains the perfectly legitimate > value NIL, which of course, you can't call anyway, thus avoiding the > issue of instantiating the formal. This is an essential difference > that would justify doing it differently for records and procedures. > > My third thought is whereas you might consider such a procedure _type_ > to have just one value, if you allow the signature in a procedure > _constant_ (i.e., an ordinary procedure declaration) to have an > empty-typed formal, you now have a value of this procedure type > other than NIL. In fact, the number of such possible values is > unbounded. Does such a procedure value make any more sense than a > value of a record with an empty-typed field? > > Right now, the compiler allows the procedure type with empty-typed > formal, a variable of that type, and assignment of NIL to the variable. > But the compiler disallows the empty-typed formal in a procedure constant > (and calls the formal a "variable" in its error message.) This seems > sensible enough to me, and I suggest we document the illegality of the > signature in a procedure constant. We could only call the formal a > variable when in the signature of a procedure constant, not a procedure > type definition, otherwise the procedure type would be illegal too. > >>> The language definition is also full of an ambiguity in its use >>> of "variable" that I have been bothered by in talking about programming >>> languages in general for years. One meaning is the meaning I have been >>> talking about, The other is the kind of variable that is declared by a >>> VAR declaration (not a VAR parameter). There are some uses in the >>> language that I think need to have this latter meaning in order to be right. >> >> Can you enumerate? >> > > Yeah, but not this minute. > >>> So we need a different or qualified term for this narrower meaning. >>> >>> On 05/23/2011 11:54 AM, Tony Hosking wrote: >>>> >>>> On May 23, 2011, at 12:45 PM, Rodney M. Bates wrote: >>>> >>>>> On 05/23/2011 09:31 AM, Tony Hosking wrote: >>>>>> An empty subrange gives a warning in the compiler. >>>>> >>>>> By my experiments, empty subrange, empty enumeration, and arrays >>>>> thereof don't warn. >>>> >>>> Sorry yes, you're right. But usage to declare any variable does. >>>> >>>>> >>>>>> But, the semantics is that it is empty, and has no values of the type. >>>>>> You cannot allocate (NEW) an empty type. >>>>>> You cannot declare a field of empty type. >>>>> >>>>> It seems odd that we have this rule for fields, but no corresponding >>>>> prohibition against arrays with empty element types. By experiments, >>>>> cm3 allows this, for both fixed and open arrays, but treats such array >>>>> types as empty types, something the language also does not say. >>>>> >>>>> At the least, the language and the compiler should agree with each other. >>>>> Maybe records/objects and arrays should be treated consistently here? >>>> >>>> Yes, I suppose so. >>>> >>>>>> Nor can you declare a variable of empty type. >>>>> >>>>> Again, oddly, there is no such prohibition in the language against >>>>> declaring a formal parameter of empty type. Cm3 prohibits it, >>>>> and calls it a 'variable' in the error message. >>>> >>>> You're right, though it's not the parameter that errors but the variable associated with the parameter. >>>> >>>>> Again, language and compiler should agree. >>>> >>>> Can you point me to the relevant entries in the language spec? >>>> >>>>> >>>>> The language also prohibits applying FIRST and LAST to the empty >>>>> enumeration, but they are OK applied to an empty subrange. >>>>> This makes sense, because they return values of the base type >>>>> of the argument type, and such values exist for an empty subrange >>>>> but not the empty enumeration, whose base type is only itself. >>>>> >>>>>> >>>>>> On May 23, 2011, at 8:41 AM, Hendrik Boom wrote: >>>>>> >>>>>>> On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: >>>>>>>> >>>>>>>> Well, I can build the whole tree and see how many times it helps. >>>>>>>> I think this is a pretty standard optimization technique. >>>>>>>> Though it'd work better with compiler-derived additional information. >>>>>>>> >>>>>>>> I initially happened upon this idea developing test cases. >>>>>>>> >>>>>>>>> The code assumes the minimum of a type is less than or equal to its maximum. >>>>>>>> >>>>>>>> I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. >>>>>>> >>>>>>> What *is* the semantics of a range whose minimum is greater than its >>>>>>> maximum? There plainly can't be any values in this range. How is a >>>>>>> variable of this tyoe initialized? Not to some arbitrary value of the >>>>>>> type, because there aren't any. I can see this type being useful to >>>>>>> admit convenient generalizations -- for example, an array with n >>>>>>> elements can still exist if n happens to be zero, but it seems to me >>>>>>> that any code involving a value of the range for subscripts for this >>>>>>> array must be simple unexecutable. >>>>>>> >>>>>>> Or is there some latitude available in the principle that a value of a >>>>>>> variable must always be of the correct type? >>>>>>> >>>>>>> -- hendrik >>>>>> >>>>>> >>>> >>>> >> >> From rodney_bates at lcwb.coop Tue May 24 22:14:59 2011 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Tue, 24 May 2011 15:14:59 -0500 Subject: [M3devel] range analysis? Message-ID: <4DDC11C3.8090303@lcwb.coop> On 05/23/2011 01:45 PM, Tony Hosking wrote: > > On May 23, 2011, at 2:26 PM, Rodney M. Bates wrote: > >> This needs more thought. On the one hand, 2.2.3 on array types allows >> the explicit element type in either kind of array type definition to >> be empty, unlike the way 2.2.4 on record types requires a field type >> to be nonempty. > > I note that an array type of empty elements is itself empty and cannot be instantiated. > Yes. >> On the other hand, 2.2 has a general prohibition against declaring a >> variable of empty type, and it is all over the language spec that the >> elements of arrays are "variables". The general definition of variable >> in 2.1 would apply to array elements. Thre are numerous places that >> describe things that can be done with a variable that we all informally >> know can be done to an element, as it should be and we all have done >> many times. Moreover, 2.2.3 says in the first paragraph that the >> elements are variables. > > So, it seems to me that we could simply disallow empty array elements and be within spec. I agree. > >> So here, the compiler is too liberal, and the language would be clearer >> with an explicit rule against empty element types. > > Right. > >> I haven't spotted anywhere a parameter is specifically called a variable, >> and it is not required to have a nonempty type in the description of >> parameter declarations. However, it certainly seems to me to fit >> the definition of variable, and as above, there are lots of things >> we know can be done with it that the language simply describes as >> doable to a variable. Moreover, for every mode, there is a rule >> that at call time, the formal is "bound to" a variable, which pretty >> well makes it variable in any context where it can be used. Even in >> a keyword binding, we are getting ready to bind it to a variable >> very soon. > > Right. > >> So maybe we need to 1) say a formal parameter is a variable, and > > A formal parameter is not in itself a variable. It's part of a type (the signature) not an implementation of that type. But every formal parameter has a corresponding variable in the body of the procedure that implements a given signature. > >> 2) say the type in a parameter declaration must be nonempty. > > This seems overwrought. I would stop simply at the variables (not the types) and let the binding of formal parameters to variables take care of the check as it currently does. > My first thought was that this argument is no more or less applicable to a procedure type containing a formal of empty type than to a record type containing a field (which is currently defined as a variable) of empty type. Both are just types constructed from other type(s), to be maybe instantiated later. In the case of the record, we now disallow the type to be constructed. Your proposal would inconsistently allow the procedure type to be constructed but complain when an attempt is made to instantiate it (i.e., call it) later. My second thought was that a procedure type with empty-typed formal is not an empty type, because it contains the perfectly legitimate value NIL, which of course, you can't call anyway, thus avoiding the issue of instantiating the formal. This is an essential difference that would justify doing it differently for records and procedures. My third thought is whereas you might consider such a procedure _type_ to have just one value, if you allow the signature in a procedure _constant_ (i.e., an ordinary procedure declaration) to have an empty-typed formal, you now have a value of this procedure type other than NIL. In fact, the number of such possible values is unbounded. Does such a procedure value make any more sense than a value of a record with an empty-typed field? Right now, the compiler allows the procedure type with empty-typed formal, a variable of that type, and assignment of NIL to the variable. But the compiler disallows the empty-typed formal in a procedure constant (and calls the formal a "variable" in its error message.) This seems sensible enough to me, and I suggest we document the illegality of the signature in a procedure constant. We could only call the formal a variable when in the signature of a procedure constant, not a procedure type definition, otherwise the procedure type would be illegal too. >> The language definition is also full of an ambiguity in its use >> of "variable" that I have been bothered by in talking about programming >> languages in general for years. One meaning is the meaning I have been >> talking about, The other is the kind of variable that is declared by a >> VAR declaration (not a VAR parameter). There are some uses in the >> language that I think need to have this latter meaning in order to be right. > > Can you enumerate? > Yeah, but not this minute. >> So we need a different or qualified term for this narrower meaning. >> >> On 05/23/2011 11:54 AM, Tony Hosking wrote: >>> >>> On May 23, 2011, at 12:45 PM, Rodney M. Bates wrote: >>> >>>> On 05/23/2011 09:31 AM, Tony Hosking wrote: >>>>> An empty subrange gives a warning in the compiler. >>>> >>>> By my experiments, empty subrange, empty enumeration, and arrays >>>> thereof don't warn. >>> >>> Sorry yes, you're right. But usage to declare any variable does. >>> >>>> >>>>> But, the semantics is that it is empty, and has no values of the type. >>>>> You cannot allocate (NEW) an empty type. >>>>> You cannot declare a field of empty type. >>>> >>>> It seems odd that we have this rule for fields, but no corresponding >>>> prohibition against arrays with empty element types. By experiments, >>>> cm3 allows this, for both fixed and open arrays, but treats such array >>>> types as empty types, something the language also does not say. >>>> >>>> At the least, the language and the compiler should agree with each other. >>>> Maybe records/objects and arrays should be treated consistently here? >>> >>> Yes, I suppose so. >>> >>>>> Nor can you declare a variable of empty type. >>>> >>>> Again, oddly, there is no such prohibition in the language against >>>> declaring a formal parameter of empty type. Cm3 prohibits it, >>>> and calls it a 'variable' in the error message. >>> >>> You're right, though it's not the parameter that errors but the variable associated with the parameter. >>> >>>> Again, language and compiler should agree. >>> >>> Can you point me to the relevant entries in the language spec? >>> >>>> >>>> The language also prohibits applying FIRST and LAST to the empty >>>> enumeration, but they are OK applied to an empty subrange. >>>> This makes sense, because they return values of the base type >>>> of the argument type, and such values exist for an empty subrange >>>> but not the empty enumeration, whose base type is only itself. >>>> >>>>> >>>>> On May 23, 2011, at 8:41 AM, Hendrik Boom wrote: >>>>> >>>>>> On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: >>>>>>> >>>>>>> Well, I can build the whole tree and see how many times it helps. >>>>>>> I think this is a pretty standard optimization technique. >>>>>>> Though it'd work better with compiler-derived additional information. >>>>>>> >>>>>>> I initially happened upon this idea developing test cases. >>>>>>> >>>>>>>> The code assumes the minimum of a type is less than or equal to its maximum. >>>>>>> >>>>>>> I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. >>>>>> >>>>>> What *is* the semantics of a range whose minimum is greater than its >>>>>> maximum? There plainly can't be any values in this range. How is a >>>>>> variable of this tyoe initialized? Not to some arbitrary value of the >>>>>> type, because there aren't any. I can see this type being useful to >>>>>> admit convenient generalizations -- for example, an array with n >>>>>> elements can still exist if n happens to be zero, but it seems to me >>>>>> that any code involving a value of the range for subscripts for this >>>>>> array must be simple unexecutable. >>>>>> >>>>>> Or is there some latitude available in the principle that a value of a >>>>>> variable must always be of the correct type? >>>>>> >>>>>> -- hendrik >>>>> >>>>> >>> >>> > From mika at async.caltech.edu Tue May 24 22:21:50 2011 From: mika at async.caltech.edu (Mika Nystrom) Date: Tue, 24 May 2011 13:21:50 -0700 Subject: [M3devel] range analysis? In-Reply-To: <4DDC11C3.8090303@lcwb.coop> References: <4DDC11C3.8090303@lcwb.coop> Message-ID: <20110524202150.5B4711A2078@async.async.caltech.edu> "Rodney M. Bates" writes: ... > >My first thought was that this argument is no more or less applicable to >a procedure type containing a formal of empty type than to a record >type containing a field (which is currently defined as a variable) >of empty type. Both are just types constructed from other type(s), >to be maybe instantiated later. In the case of the record, we now >disallow the type to be constructed. Your proposal would inconsistently >allow the procedure type to be constructed but complain when an >attempt is made to instantiate it (i.e., call it) later. > >My second thought was that a procedure type with empty-typed formal >is not an empty type, because it contains the perfectly legitimate >value NIL, which of course, you can't call anyway, thus avoiding the >issue of instantiating the formal. This is an essential difference >that would justify doing it differently for records and procedures. > By this logic, shoudln't you also allow such types to be fields in OBJECT types? What about REF RECORD types? Mika From rodney_bates at lcwb.coop Wed May 25 16:54:01 2011 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Wed, 25 May 2011 09:54:01 -0500 Subject: [M3devel] range analysis? In-Reply-To: <919256C9-1773-43EC-9B62-C45883935957@cs.purdue.edu> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> <4DDA8F1A.3070207@lcwb.coop> <8C9E1E77-686F-42E0-87FA-B573A4A02CC9@cs.purdue.edu> <4DDAA6EC.8060401@lcwb.coop> <45B5D160-9E80-4BB9-8411-F3976BCDC207@cs.purdue.edu> <4DDAF56D.8010505@lcwb.coop> <919256C9-1773-43EC-9B62-C45883935957@cs.purdue.edu> Message-ID: <4DDD1809.3030108@lcwb.coop> Yes. Keep the current behavior of the compiler (formal with empty-type is legal in a procedure type, but not in a procedure constant) and document it. On 05/23/2011 09:06 PM, Tony Hosking wrote: > Sorry for the terse response. Is there a proposal buried in there? > > On May 23, 2011, at 8:01 PM, Rodney M. Bates wrote: > >> >> >> On 05/23/2011 01:45 PM, Tony Hosking wrote: >>> >>> On May 23, 2011, at 2:26 PM, Rodney M. Bates wrote: >>> >>>> This needs more thought. On the one hand, 2.2.3 on array types allows >>>> the explicit element type in either kind of array type definition to >>>> be empty, unlike the way 2.2.4 on record types requires a field type >>>> to be nonempty. >>> >>> I note that an array type of empty elements is itself empty and cannot be instantiated. >>> >> >> Yes. >> >>>> On the other hand, 2.2 has a general prohibition against declaring a >>>> variable of empty type, and it is all over the language spec that the >>>> elements of arrays are "variables". The general definition of variable >>>> in 2.1 would apply to array elements. Thre are numerous places that >>>> describe things that can be done with a variable that we all informally >>>> know can be done to an element, as it should be and we all have done >>>> many times. Moreover, 2.2.3 says in the first paragraph that the >>>> elements are variables. >>> >>> So, it seems to me that we could simply disallow empty array elements and be within spec. >> >> I agree. >> >>> >>>> So here, the compiler is too liberal, and the language would be clearer >>>> with an explicit rule against empty element types. >>> >>> Right. >>> >>>> I haven't spotted anywhere a parameter is specifically called a variable, >>>> and it is not required to have a nonempty type in the description of >>>> parameter declarations. However, it certainly seems to me to fit >>>> the definition of variable, and as above, there are lots of things >>>> we know can be done with it that the language simply describes as >>>> doable to a variable. Moreover, for every mode, there is a rule >>>> that at call time, the formal is "bound to" a variable, which pretty >>>> well makes it variable in any context where it can be used. Even in >>>> a keyword binding, we are getting ready to bind it to a variable >>>> very soon. >>> >>> Right. >>> >>>> So maybe we need to 1) say a formal parameter is a variable, and >>> >>> A formal parameter is not in itself a variable. It's part of a type (the signature) not an implementation of that type. But every formal parameter has a corresponding variable in the body of the procedure that implements a given signature. >>> >>>> 2) say the type in a parameter declaration must be nonempty. >>> >>> This seems overwrought. I would stop simply at the variables (not the types) and let the binding of formal parameters to variables take care of the check as it currently does. >>> >> >> My first thought was that this argument is no more or less applicable to >> a procedure type containing a formal of empty type than to a record >> type containing a field (which is currently defined as a variable) >> of empty type. Both are just types constructed from other type(s), >> to be maybe instantiated later. In the case of the record, we now >> disallow the type to be constructed. Your proposal would inconsistently >> allow the procedure type to be constructed but complain when an >> attempt is made to instantiate it (i.e., call it) later. >> >> My second thought was that a procedure type with empty-typed formal >> is not an empty type, because it contains the perfectly legitimate >> value NIL, which of course, you can't call anyway, thus avoiding the >> issue of instantiating the formal. This is an essential difference >> that would justify doing it differently for records and procedures. >> >> My third thought is whereas you might consider such a procedure _type_ >> to have just one value, if you allow the signature in a procedure >> _constant_ (i.e., an ordinary procedure declaration) to have an >> empty-typed formal, you now have a value of this procedure type >> other than NIL. In fact, the number of such possible values is >> unbounded. Does such a procedure value make any more sense than a >> value of a record with an empty-typed field? >> >> Right now, the compiler allows the procedure type with empty-typed >> formal, a variable of that type, and assignment of NIL to the variable. >> But the compiler disallows the empty-typed formal in a procedure constant >> (and calls the formal a "variable" in its error message.) This seems >> sensible enough to me, and I suggest we document the illegality of the >> signature in a procedure constant. We could only call the formal a >> variable when in the signature of a procedure constant, not a procedure >> type definition, otherwise the procedure type would be illegal too. >> >>>> The language definition is also full of an ambiguity in its use >>>> of "variable" that I have been bothered by in talking about programming >>>> languages in general for years. One meaning is the meaning I have been >>>> talking about, The other is the kind of variable that is declared by a >>>> VAR declaration (not a VAR parameter). There are some uses in the >>>> language that I think need to have this latter meaning in order to be right. >>> >>> Can you enumerate? >>> >> >> Yeah, but not this minute. >> >>>> So we need a different or qualified term for this narrower meaning. >>>> >>>> On 05/23/2011 11:54 AM, Tony Hosking wrote: >>>>> >>>>> On May 23, 2011, at 12:45 PM, Rodney M. Bates wrote: >>>>> >>>>>> On 05/23/2011 09:31 AM, Tony Hosking wrote: >>>>>>> An empty subrange gives a warning in the compiler. >>>>>> >>>>>> By my experiments, empty subrange, empty enumeration, and arrays >>>>>> thereof don't warn. >>>>> >>>>> Sorry yes, you're right. But usage to declare any variable does. >>>>> >>>>>> >>>>>>> But, the semantics is that it is empty, and has no values of the type. >>>>>>> You cannot allocate (NEW) an empty type. >>>>>>> You cannot declare a field of empty type. >>>>>> >>>>>> It seems odd that we have this rule for fields, but no corresponding >>>>>> prohibition against arrays with empty element types. By experiments, >>>>>> cm3 allows this, for both fixed and open arrays, but treats such array >>>>>> types as empty types, something the language also does not say. >>>>>> >>>>>> At the least, the language and the compiler should agree with each other. >>>>>> Maybe records/objects and arrays should be treated consistently here? >>>>> >>>>> Yes, I suppose so. >>>>> >>>>>>> Nor can you declare a variable of empty type. >>>>>> >>>>>> Again, oddly, there is no such prohibition in the language against >>>>>> declaring a formal parameter of empty type. Cm3 prohibits it, >>>>>> and calls it a 'variable' in the error message. >>>>> >>>>> You're right, though it's not the parameter that errors but the variable associated with the parameter. >>>>> >>>>>> Again, language and compiler should agree. >>>>> >>>>> Can you point me to the relevant entries in the language spec? >>>>> >>>>>> >>>>>> The language also prohibits applying FIRST and LAST to the empty >>>>>> enumeration, but they are OK applied to an empty subrange. >>>>>> This makes sense, because they return values of the base type >>>>>> of the argument type, and such values exist for an empty subrange >>>>>> but not the empty enumeration, whose base type is only itself. >>>>>> >>>>>>> >>>>>>> On May 23, 2011, at 8:41 AM, Hendrik Boom wrote: >>>>>>> >>>>>>>> On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: >>>>>>>>> >>>>>>>>> Well, I can build the whole tree and see how many times it helps. >>>>>>>>> I think this is a pretty standard optimization technique. >>>>>>>>> Though it'd work better with compiler-derived additional information. >>>>>>>>> >>>>>>>>> I initially happened upon this idea developing test cases. >>>>>>>>> >>>>>>>>>> The code assumes the minimum of a type is less than or equal to its maximum. >>>>>>>>> >>>>>>>>> I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. >>>>>>>> >>>>>>>> What *is* the semantics of a range whose minimum is greater than its >>>>>>>> maximum? There plainly can't be any values in this range. How is a >>>>>>>> variable of this tyoe initialized? Not to some arbitrary value of the >>>>>>>> type, because there aren't any. I can see this type being useful to >>>>>>>> admit convenient generalizations -- for example, an array with n >>>>>>>> elements can still exist if n happens to be zero, but it seems to me >>>>>>>> that any code involving a value of the range for subscripts for this >>>>>>>> array must be simple unexecutable. >>>>>>>> >>>>>>>> Or is there some latitude available in the principle that a value of a >>>>>>>> variable must always be of the correct type? >>>>>>>> >>>>>>>> -- hendrik >>>>>>> >>>>>>> >>>>> >>>>> >>> >>> > > From rodney_bates at lcwb.coop Wed May 25 17:55:11 2011 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Wed, 25 May 2011 10:55:11 -0500 Subject: [M3devel] range analysis? In-Reply-To: <20110524202150.5B4711A2078@async.async.caltech.edu> References: <4DDC11C3.8090303@lcwb.coop> <20110524202150.5B4711A2078@async.async.caltech.edu> Message-ID: <4DDD265F.3020102@lcwb.coop> On 05/24/2011 03:21 PM, Mika Nystrom wrote: > "Rodney M. Bates" writes: > ... >> >> My first thought was that this argument is no more or less applicable to >> a procedure type containing a formal of empty type than to a record >> type containing a field (which is currently defined as a variable) >> of empty type. Both are just types constructed from other type(s), >> to be maybe instantiated later. In the case of the record, we now >> disallow the type to be constructed. Your proposal would inconsistently >> allow the procedure type to be constructed but complain when an >> attempt is made to instantiate it (i.e., call it) later. >> >> My second thought was that a procedure type with empty-typed formal >> is not an empty type, because it contains the perfectly legitimate >> value NIL, which of course, you can't call anyway, thus avoiding the >> issue of instantiating the formal. This is an essential difference >> that would justify doing it differently for records and procedures. >> > > By this logic, shoudln't you also allow such types to be fields > in OBJECT types? Yes. But neither the language nor the compiler allow this. The compiler gives no error on subsequent attempt to allocate such an object, but this is probably just secondary. What about REF RECORD types? REF EmptyType is OK, and the compiler allows it to be defined but not allocated. But the only ways right now to get an empty type are an empty enumeration, empty subrange, or array of empty-typed elements. Try to construct a record with an empty-typed field and the type definition fails. I am doing more compiler experiments and language reading. It looks like we have some inconsistencies. > > Mika > From dabenavidesd at yahoo.es Wed May 25 18:30:51 2011 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Wed, 25 May 2011 17:30:51 +0100 (BST) Subject: [M3devel] range analysis? In-Reply-To: <4DDD265F.3020102@lcwb.coop> Message-ID: <812997.17365.qm@web29709.mail.ird.yahoo.com> Hi all: well that said, please you may take a look at this manual (from p8): http://research.microsoft.com/en-us/um/people/blampson/32a-CedarLang/32a-CedarLangOCR.doc Modula-3 has an action semantics description (not very notorious): http://www.dcs.gla.ac.uk/~daw/publications/M3AS.ps And in the same way: http://research.microsoft.com/en-us/um/people/blampson/48-POCScourse/48-POCS2006.pdf page 24 Thanks in advance, hope it helps a bit --- El mi?, 25/5/11, Rodney M. Bates escribi?: > De: Rodney M. Bates > Asunto: Re: [M3devel] range analysis? > Para: m3devel at elegosoft.com > Fecha: mi?rcoles, 25 de mayo, 2011 10:55 > > > On 05/24/2011 03:21 PM, Mika Nystrom wrote: > > "Rodney M. Bates" writes: > > ... > >> > >> My first thought was that this argument is no more > or less applicable to > >> a procedure type containing a formal of empty type > than to a record > >> type containing a field (which is currently > defined as a variable) > >> of empty type. Both are just types > constructed from other type(s), > >> to be maybe instantiated later. In the case > of the record, we now > >> disallow the type to be constructed. Your > proposal would inconsistently > >> allow the procedure type to be constructed but > complain when an > >> attempt is made to instantiate it (i.e., call it) > later. > >> > >> My second thought was that a procedure type with > empty-typed formal > >> is not an empty type, because it contains the > perfectly legitimate > >> value NIL, which of course, you can't call anyway, > thus avoiding the > >> issue of instantiating the formal. This is > an essential difference > >> that would justify doing it differently for > records and procedures. > >> > > > > By this logic, shoudln't you also allow such types to > be fields > > in OBJECT types? > > Yes. But neither the language nor the compiler allow > this. The > compiler gives no error on subsequent attempt to allocate > such an object, > but this is probably just secondary. > > What about REF RECORD types? > > REF EmptyType is OK, and the compiler allows it to be > defined > but not allocated. But the only ways right now to get > an empty > type are an empty enumeration, empty subrange, or array of > empty-typed elements. Try to construct a record with > an > empty-typed field and the type definition fails. > > I am doing more compiler experiments and language reading. > It looks like we have some inconsistencies. > > > > > Mika > > > From dabenavidesd at yahoo.es Thu May 26 00:38:34 2011 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Wed, 25 May 2011 23:38:34 +0100 (BST) Subject: [M3devel] About modula3.org and modula-3 domain Message-ID: <36867.43808.qm@web29703.mail.ird.yahoo.com> Hi all: has anyone devised an opportunity to have it, or if it is of any help, when would one become important one doesn't know (important for others than us), then if so what do you think and (are you) waiting? :) If any interest in others please if you speak up (e.g .com, et al). Thanks in advance From dabenavidesd at yahoo.es Fri May 27 05:18:16 2011 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Fri, 27 May 2011 04:18:16 +0100 (BST) Subject: [M3devel] About modula3.org and modula-3 domain In-Reply-To: <36867.43808.qm@web29703.mail.ird.yahoo.com> Message-ID: <161903.96505.qm@web29710.mail.ird.yahoo.com> Hi all: and please start to think where we want to go, all your wildest Modula dreams might become true: http://www.ic.unicamp.br/~stolfi/PUB/misc/misc/ramblings/comp/modula/M3-99Wishes.msg http://www.ic.unicamp.br/~stolfi/PUB/misc/misc/ramblings/comp/ReversingGuardedPrograms.mgs http://www.ic.unicamp.br/~stolfi/PUB/misc/misc/ramblings/comp/ReversingGuardedPrograms.mgs Yeah, type inference, plus guarded commands built into language and some Modula-3 Modula type generics type reconstruction before compile time (type checking), and then object generics, who wants to work for (much of this currently solved, who can say about that any other language)? So, maybe its more profitable to start deploying modula4 modula-4 dot com, co, etc at al. I guess you would believe it. PS Finally, all type checking type inferencer and verfication condition generator sound and why not heck complete (so everything is always true it's safe and not UNSAFE) Thanks in advance --- El mi?, 25/5/11, Daniel Alejandro Benavides D. escribi?: > De: Daniel Alejandro Benavides D. > Asunto: [M3devel] About modula3.org and modula-3 domain > Para: m3devel at elegosoft.com > Fecha: mi?rcoles, 25 de mayo, 2011 17:38 > Hi all: > has anyone devised an opportunity to have it, or if it is > of any help, when would one become important one doesn't > know (important for others than us), then if so what do you > think and (are you) waiting? :) > If any interest in others please if you speak up (e.g .com, > et al). > Thanks in advance > From dabenavidesd at yahoo.es Tue May 31 22:12:52 2011 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Tue, 31 May 2011 21:12:52 +0100 (BST) Subject: [M3devel] About modula3.org and modula-3 domain In-Reply-To: <161903.96505.qm@web29710.mail.ird.yahoo.com> Message-ID: <850866.31542.qm@web29713.mail.ird.yahoo.com> Hi all: well, instead of redirection, what about mirroring? We have already a public machine here to do that (first ip #, later another domain I guess or), which ports will we needed to open (does dcvs installation help)? Thanks in advance --- El jue, 26/5/11, Daniel Alejandro Benavides D. escribi?: > De: Daniel Alejandro Benavides D. > Asunto: Re: [M3devel] About modula3.org and modula-3 domain > Para: m3devel at elegosoft.com > Fecha: jueves, 26 de mayo, 2011 22:18 > Hi all: > and please start to think where we want to go, all your > wildest Modula dreams might become true: > http://www.ic.unicamp.br/~stolfi/PUB/misc/misc/ramblings/comp/modula/M3-99Wishes.msg > > http://www.ic.unicamp.br/~stolfi/PUB/misc/misc/ramblings/comp/ReversingGuardedPrograms.mgs > > http://www.ic.unicamp.br/~stolfi/PUB/misc/misc/ramblings/comp/ReversingGuardedPrograms.mgs > > Yeah, type inference, plus guarded commands built into > language and some Modula-3 Modula type generics type > reconstruction before compile time (type checking), and then > object generics, who wants to work for (much of this > currently solved, who can say about that any other > language)? > > So, maybe its more profitable to start deploying modula4 > modula-4 dot com, co, etc at al. I guess you would believe > it. > > PS Finally, all type checking type inferencer and > verfication condition generator sound and why not heck > complete (so everything is always true it's safe and not > UNSAFE) > > Thanks in advance > > --- El mi?, 25/5/11, Daniel Alejandro Benavides D. > escribi?: > > > De: Daniel Alejandro Benavides D. > > Asunto: [M3devel] About modula3.org and modula-3 > domain > > Para: m3devel at elegosoft.com > > Fecha: mi?rcoles, 25 de mayo, 2011 17:38 > > Hi all: > > has anyone devised an opportunity to have it, or if it > is > > of any help, when would one become important one > doesn't > > know (important for others than us), then if so what > do you > > think and (are you) waiting? :) > > If any interest in others please if you speak up (e.g > .com, > > et al). > > Thanks in advance > > > From rcolebur at SCIRES.COM Sun May 15 05:57:06 2011 From: rcolebur at SCIRES.COM (Coleburn, Randy) Date: Sat, 14 May 2011 23:57:06 -0400 Subject: [M3devel] stubgen problem with m3-tools\m3tk\src\toolmisc\M3Error.m3 line 214 Message-ID: I am seeing a new error when building on Windows 2000, XP, and 7. The error affects at least the following packages: * zeus * obliqrt * obliqparse * juno-app The problem is manifested when running the stub generator (stubgen). In all cases it reports a runtime error, attempt to reference an illegal memory location, and the file and line reference is always to line #214 in m3-tools\m3tk\src\toolmisc\M3Error.m3 I suspect some recent change is the culprit. Here is an example of the error when building juno-app: C:\cm3\bin\stubgen -v1 -sno RemoteView.T -T.M3IMPTAB *** *** runtime error: *** Attempt to reference an illegal memory location. *** file "..\src\toolmisc\M3Error.m3", line 214 *** Stack trace: FP PC Procedure --------- --------- ------------------------------- 0x37f208 0xdd496c CarefulNodeLookup + 0x1e in ..\src\toolmisc\M3Error.m3 0x37f26c 0xdd4401 RecordError + 0x2e8 in ..\src\toolmisc\M3Error.m3 0x37f298 0xdd4026 Report + 0x23 in ..\src\toolmisc\M3Error.m3 0x37f308 0xe46703 Eval + 0x220 in ..\src\sem\M3CExpValue.m3 0x37f358 0xe48773 Set + 0x672 in ..\src\sem\M3CExpValue.m3 0x37f380 0xda645b DoVisit + 0x121 in ..\src\gast\ASTWalk.m3 0x37f3a4 0xe381de Range + 0x85 in ..\src\ast\M3AST_AS_Walk.m3 0x37f3c8 0xda63e8 DoVisit + 0xae in ..\src\gast\ASTWalk.m3 0x37f3ec 0xe36a81 Subrange_type + 0x85 in ..\src\ast\M3AST_AS_Walk.m3 0x37f410 0xda63e8 DoVisit + 0xae in ..\src\gast\ASTWalk.m3 ......... ......... ... more frames ... "C:\cm3\pkg\netobj\src\netobj.tmpl", line 37: quake runtime error: exit 2147483647: C:\cm3\bin\stubgen -v1 -sno RemoteView.T -T.M3IMPTAB --procedure-- -line- -file--- exec -- _v_netobj 37 C:\cm3\pkg\netobj\src\netobj.tmpl netobjv1 44 C:\cm3\pkg\netobj\src\netobj.tmpl netobj 64 C:\cm3\pkg\netobj\src\netobj.tmpl include_dir 105 C:\cm3\Sandbox\m3-ui\juno-2\juno-app\src\m3makefile 4 C:\cm3\Sandbox\m3-ui\juno-2\juno-app\NT386\m3make.args Fatal Error: package build failed WARNING: Encountered an error when processing package "m3-ui\juno-2\juno-app" for "-build". Regards, Randy Coleburn -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Sun May 15 15:46:14 2011 From: hosking at cs.purdue.edu (Tony Hosking) Date: Sun, 15 May 2011 09:46:14 -0400 Subject: [M3devel] stubgen problem with m3-tools\m3tk\src\toolmisc\M3Error.m3 line 214 In-Reply-To: References: Message-ID: There have been recent changes to m3tk. I think by Mika? Sent from my iPad On 14/05/2011, at 11:57 PM, "Coleburn, Randy" wrote: > I am seeing a new error when building on Windows 2000, XP, and 7. > > > > The error affects at least the following packages: > > ? zeus > > ? obliqrt > > ? obliqparse > > ? juno-app > > > > The problem is manifested when running the stub generator (stubgen). In all cases it reports a runtime error, attempt to reference an illegal memory location, and the file and line reference is always to line #214 in m3-tools\m3tk\src\toolmisc\M3Error.m3 > > > > I suspect some recent change is the culprit. > > > > Here is an example of the error when building juno-app: > > > > C:\cm3\bin\stubgen -v1 -sno RemoteView.T -T.M3IMPTAB > > > > > > *** > > *** runtime error: > > *** Attempt to reference an illegal memory location. > > *** file "..\src\toolmisc\M3Error.m3", line 214 > > *** > > > > Stack trace: > > FP PC Procedure > > --------- --------- ------------------------------- > > 0x37f208 0xdd496c CarefulNodeLookup + 0x1e in ..\src\toolmisc\M3Error.m3 > > 0x37f26c 0xdd4401 RecordError + 0x2e8 in ..\src\toolmisc\M3Error.m3 > > 0x37f298 0xdd4026 Report + 0x23 in ..\src\toolmisc\M3Error.m3 > > 0x37f308 0xe46703 Eval + 0x220 in ..\src\sem\M3CExpValue.m3 > > 0x37f358 0xe48773 Set + 0x672 in ..\src\sem\M3CExpValue.m3 > > 0x37f380 0xda645b DoVisit + 0x121 in ..\src\gast\ASTWalk.m3 > > 0x37f3a4 0xe381de Range + 0x85 in ..\src\ast\M3AST_AS_Walk.m3 > > 0x37f3c8 0xda63e8 DoVisit + 0xae in ..\src\gast\ASTWalk.m3 > > 0x37f3ec 0xe36a81 Subrange_type + 0x85 in ..\src\ast\M3AST_AS_Walk.m3 > > 0x37f410 0xda63e8 DoVisit + 0xae in ..\src\gast\ASTWalk.m3 > > ......... ......... ... more frames ... > > "C:\cm3\pkg\netobj\src\netobj.tmpl", line 37: quake runtime error: exit 2147483647: C:\cm3\bin\stubgen -v1 -sno RemoteView.T -T.M3IMPTAB > > > > --procedure-- -line- -file--- > > exec -- > > _v_netobj 37 C:\cm3\pkg\netobj\src\netobj.tmpl > > netobjv1 44 C:\cm3\pkg\netobj\src\netobj.tmpl > > netobj 64 C:\cm3\pkg\netobj\src\netobj.tmpl > > include_dir 105 C:\cm3\Sandbox\m3-ui\juno-2\juno-app\src\m3makefile > > 4 C:\cm3\Sandbox\m3-ui\juno-2\juno-app\NT386\m3make.args > > > > Fatal Error: package build failed > > > > WARNING: Encountered an error when processing package "m3-ui\juno-2\juno-app" for "-build". > > > > Regards, > > Randy Coleburn -------------- next part -------------- An HTML attachment was scrubbed... URL: From rodney_bates at lcwb.coop Sun May 15 19:08:21 2011 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Sun, 15 May 2011 12:08:21 -0500 Subject: [M3devel] stubgen problem with m3-tools\m3tk\src\toolmisc\M3Error.m3 line 214 In-Reply-To: References: Message-ID: <4DD00885.7040006@lcwb.coop> Hmm, I checked in a change to the head on 2011-4-26 that could lie right on this backtrace. It is in M3CExpValue.Eval, and contains a call on M3Error.Report. There are several other calls in M3CExpValue.Eval to M3Error.Report, not involving my change. Simple proportioning between hex displacements and source line counts suggests it is the call in the change. But it is hard to image how my change could do anything but reduce the set of cases where this call is executed, and any such cases remaining sould have been with the same values of all variables, compared to before. Moreover, this or any of the calls in Eval on Report would have been producing error messages before the change. I presume there were no such error messages formerly? Are there any LONGINT literals in the code stubgen is being run on? The change only weakens an overzealous error check for them. On 05/14/2011 10:57 PM, Coleburn, Randy wrote: > I am seeing a new error when building on Windows 2000, XP, and 7. > > The error affects at least the following packages: > > ?zeus > > ?obliqrt > > ?obliqparse > > ?juno-app > > The problem is manifested when running the stub generator (stubgen). In all cases it reports a runtime error, attempt to reference an illegal memory location, and the file and line reference is always to line #*214* in *m3-tools\m3tk\src\toolmisc\M3Error.m3* > > I suspect some recent change is the culprit. > > Here is an example of the error when building juno-app: > > C:\cm3\bin\stubgen -v1 -sno RemoteView.T -T.M3IMPTAB > > *** > > *** runtime error: > > *** Attempt to reference an illegal memory location. > > *** file "..\src\toolmisc\M3Error.m3", line 214 > > *** > > Stack trace: > > FP PC Procedure > > --------- --------- ------------------------------- > > 0x37f208 0xdd496c CarefulNodeLookup + 0x1e in ..\src\toolmisc\M3Error.m3 > > 0x37f26c 0xdd4401 RecordError + 0x2e8 in ..\src\toolmisc\M3Error.m3 > > 0x37f298 0xdd4026 Report + 0x23 in ..\src\toolmisc\M3Error.m3 > > 0x37f308 0xe46703 Eval + 0x220 in ..\src\sem\M3CExpValue.m3 > > 0x37f358 0xe48773 Set + 0x672 in ..\src\sem\M3CExpValue.m3 > > 0x37f380 0xda645b DoVisit + 0x121 in ..\src\gast\ASTWalk.m3 > > 0x37f3a4 0xe381de Range + 0x85 in ..\src\ast\M3AST_AS_Walk.m3 > > 0x37f3c8 0xda63e8 DoVisit + 0xae in ..\src\gast\ASTWalk.m3 > > 0x37f3ec 0xe36a81 Subrange_type + 0x85 in ..\src\ast\M3AST_AS_Walk.m3 > > 0x37f410 0xda63e8 DoVisit + 0xae in ..\src\gast\ASTWalk.m3 > > ......... ......... ... more frames ... > > "C:\cm3\pkg\netobj\src\netobj.tmpl", line 37: quake runtime error: exit 2147483647: C:\cm3\bin\stubgen -v1 -sno RemoteView.T -T.M3IMPTAB > > --procedure-- -line- -file--- > > exec -- > > _v_netobj 37 C:\cm3\pkg\netobj\src\netobj.tmpl > > netobjv1 44 C:\cm3\pkg\netobj\src\netobj.tmpl > > netobj 64 C:\cm3\pkg\netobj\src\netobj.tmpl > > include_dir 105 C:\cm3\Sandbox\m3-ui\juno-2\juno-app\src\m3makefile > > 4 C:\cm3\Sandbox\m3-ui\juno-2\juno-app\NT386\m3make.args > > Fatal Error: package build failed > > WARNING: Encountered an error when processing package "m3-ui\juno-2\juno-app" for "-build". > > Regards, > > Randy Coleburn > From mika at async.caltech.edu Sun May 15 19:23:22 2011 From: mika at async.caltech.edu (Mika Nystrom) Date: Sun, 15 May 2011 10:23:22 -0700 Subject: [M3devel] stubgen problem with m3-tools\m3tk\src\toolmisc\M3Error.m3 line 214 In-Reply-To: <4DD00885.7040006@lcwb.coop> References: <4DD00885.7040006@lcwb.coop> Message-ID: <20110515172322.0D5AC1A2078@async.async.caltech.edu> Stupid question: you did "make clean" (or equivalent) first, right? I've noticed CM3 is pretty bad about detecting changes (at least compared to PM3, which is my basis for all Modula-3 comparisons) and can easily make corrupted binaries if you change things and rely on incremental compilation---at least. if an interface has changed, which I suppose extends to opaque information too. BTW, I have reviewing the LONGINT/m3tk change and Jay's -pthread change on my todo list. CM3 just has been pushed down a bit for a while, hope to get to them soon, not ignoring you guys. Looks to me like something is forgetting to call M3Error.SetCu. Not code I've ever gone near... Mika "Rodney M. Bates" writes: >Hmm, I checked in a change to the head on 2011-4-26 that could lie right on >this backtrace. It is in M3CExpValue.Eval, and contains a call on M3Error.Rep >ort. >There are several other calls in M3CExpValue.Eval to M3Error.Report, not invol >ving >my change. Simple proportioning between hex displacements and source line cou >nts >suggests it is the call in the change. > >But it is hard to image how my change could do anything but reduce the set of >cases where this call is executed, and any such cases remaining sould have bee >n >with the same values of all variables, compared to before. > >Moreover, this or any of the calls in Eval on Report would have been producing >error messages before the change. I presume there were no such error messages >formerly? > >Are there any LONGINT literals in the code stubgen is being run on? The chang >e >only weakens an overzealous error check for them. > >On 05/14/2011 10:57 PM, Coleburn, Randy wrote: >> I am seeing a new error when building on Windows 2000, XP, and 7. >> >> The error affects at least the following packages: >> >> ?zeus >> >> ?obliqrt >> >> ?obliqparse >> >> ?juno-app >> >> The problem is manifested when running the stub generator (stubgen). In all >cases it reports a runtime error, attempt to reference an illegal memory locat >ion, and the file and line reference is always to line #*214* in *m3-tools\m3t >k\src\toolmisc\M3Error.m3* >> >> I suspect some recent change is the culprit. >> >> Here is an example of the error when building juno-app: >> >> C:\cm3\bin\stubgen -v1 -sno RemoteView.T -T.M3IMPTAB >> >> *** >> >> *** runtime error: >> >> *** Attempt to reference an illegal memory location. >> >> *** file "..\src\toolmisc\M3Error.m3", line 214 >> >> *** >> >> Stack trace: >> >> FP PC Procedure >> >> --------- --------- ------------------------------- >> >> 0x37f208 0xdd496c CarefulNodeLookup + 0x1e in ..\src\toolmisc\M3Error.m3 >> >> 0x37f26c 0xdd4401 RecordError + 0x2e8 in ..\src\toolmisc\M3Error.m3 >> >> 0x37f298 0xdd4026 Report + 0x23 in ..\src\toolmisc\M3Error.m3 >> >> 0x37f308 0xe46703 Eval + 0x220 in ..\src\sem\M3CExpValue.m3 >> >> 0x37f358 0xe48773 Set + 0x672 in ..\src\sem\M3CExpValue.m3 >> >> 0x37f380 0xda645b DoVisit + 0x121 in ..\src\gast\ASTWalk.m3 >> >> 0x37f3a4 0xe381de Range + 0x85 in ..\src\ast\M3AST_AS_Walk.m3 >> >> 0x37f3c8 0xda63e8 DoVisit + 0xae in ..\src\gast\ASTWalk.m3 >> >> 0x37f3ec 0xe36a81 Subrange_type + 0x85 in ..\src\ast\M3AST_AS_Walk.m3 >> >> 0x37f410 0xda63e8 DoVisit + 0xae in ..\src\gast\ASTWalk.m3 >> >> ......... ......... ... more frames ... >> >> "C:\cm3\pkg\netobj\src\netobj.tmpl", line 37: quake runtime error: exit 2147 >483647: C:\cm3\bin\stubgen -v1 -sno RemoteView.T -T.M3IMPTAB >> >> --procedure-- -line- -file--- >> >> exec -- >> >> _v_netobj 37 C:\cm3\pkg\netobj\src\netobj.tmpl >> >> netobjv1 44 C:\cm3\pkg\netobj\src\netobj.tmpl >> >> netobj 64 C:\cm3\pkg\netobj\src\netobj.tmpl >> >> include_dir 105 C:\cm3\Sandbox\m3-ui\juno-2\juno-app\src\m3makefile >> >> 4 C:\cm3\Sandbox\m3-ui\juno-2\juno-app\NT386\m3make.args >> >> Fatal Error: package build failed >> >> WARNING: Encountered an error when processing package "m3-ui\juno-2\juno-app >" for "-build". >> >> Regards, >> >> Randy Coleburn >> From rcolebur at SCIRES.COM Sun May 15 23:30:58 2011 From: rcolebur at SCIRES.COM (Coleburn, Randy) Date: Sun, 15 May 2011 17:30:58 -0400 Subject: [M3devel] [M3commit] CVS Update: cm3 In-Reply-To: <20110515210259.1804D24740E9@birch.elegosoft.com> References: <20110515210259.1804D24740E9@birch.elegosoft.com> Message-ID: Rodney: Thanks. I've confirmed that your fix seems to solve the problem. Regards, Randy Coleburn -----Original Message----- From: Rodney M. Bates [mailto:rodney at elego.de] Sent: Sunday, May 15, 2011 7:03 PM To: m3commit at elegosoft.com Subject: [M3commit] CVS Update: cm3 CVSROOT: /usr/cvs Changes by: rodney at birch. 11/05/15 23:02:58 Modified files: cm3/m3-tools/m3tk/src/fe/: M3CGo.m3 Log message: Fix a bug in m3tk that was uncovered by previous fix to LONGINT literal checking, causing NIL deref crashes. M3Go.CompileUnit was failing to call M3Error.SetCu, leaving no current unit for error messages. There are other mysteries here, but this cures the crash and reproduces previous output for at least one case. From rodney_bates at lcwb.coop Mon May 16 14:52:19 2011 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Mon, 16 May 2011 07:52:19 -0500 Subject: [M3devel] stubgen problem with m3-tools\m3tk\src\toolmisc\M3Error.m3 line 214 Message-ID: <4DD11E03.7080502@lcwb.coop> On 05/15/2011 12:23 PM, Mika Nystrom wrote: > Stupid question: > > you did "make clean" (or equivalent) first, right? > > I've noticed CM3 is pretty bad about detecting changes (at least compared > to PM3, which is my basis for all Modula-3 comparisons) and can easily > make corrupted binaries if you change things and rely on incremental > compilation---at least. if an interface has changed, which I suppose > extends to opaque information too. > > BTW, I have reviewing the LONGINT/m3tk change and Jay's -pthread change > on my todo list. CM3 just has been pushed down a bit for a while, hope > to get to them soon, not ignoring you guys. > > Looks to me like something is forgetting to call M3Error.SetCu. Not > code I've ever gone near... Yes, I just found this and checked in a fix in the head. This was a long- standing bug, but was uncovered by my recent change. There is still more to investigate here: - It looks like M3CLex.ReadNumericLiteral is not putting the 'L' into the literal. - It looks like M3CLex.ReadHexDigits won't recognize the 'L' at all, for a based literal. - It looks like somewhere even "0" is getting typed as Longint_literal. As I remember, later processing of LONGINT literals will tolerate the trailing 'L'. > > Mika > > "Rodney M. Bates" writes: >> Hmm, I checked in a change to the head on 2011-4-26 that could lie right on >> this backtrace. It is in M3CExpValue.Eval, and contains a call on M3Error.Rep >> ort. >> There are several other calls in M3CExpValue.Eval to M3Error.Report, not invol >> ving >> my change. Simple proportioning between hex displacements and source line cou >> nts >> suggests it is the call in the change. >> >> But it is hard to image how my change could do anything but reduce the set of >> cases where this call is executed, and any such cases remaining sould have bee >> n >> with the same values of all variables, compared to before. >> >> Moreover, this or any of the calls in Eval on Report would have been producing >> error messages before the change. I presume there were no such error messages >> formerly? >> >> Are there any LONGINT literals in the code stubgen is being run on? The chang >> e >> only weakens an overzealous error check for them. >> >> On 05/14/2011 10:57 PM, Coleburn, Randy wrote: >>> I am seeing a new error when building on Windows 2000, XP, and 7. >>> >>> The error affects at least the following packages: >>> >>> ?zeus >>> >>> ?obliqrt >>> >>> ?obliqparse >>> >>> ?juno-app >>> >>> The problem is manifested when running the stub generator (stubgen). In all >> cases it reports a runtime error, attempt to reference an illegal memory locat >> ion, and the file and line reference is always to line #*214* in *m3-tools\m3t >> k\src\toolmisc\M3Error.m3* >>> >>> I suspect some recent change is the culprit. >>> >>> Here is an example of the error when building juno-app: >>> >>> C:\cm3\bin\stubgen -v1 -sno RemoteView.T -T.M3IMPTAB >>> >>> *** >>> >>> *** runtime error: >>> >>> *** Attempt to reference an illegal memory location. >>> >>> *** file "..\src\toolmisc\M3Error.m3", line 214 >>> >>> *** >>> >>> Stack trace: >>> >>> FP PC Procedure >>> >>> --------- --------- ------------------------------- >>> >>> 0x37f208 0xdd496c CarefulNodeLookup + 0x1e in ..\src\toolmisc\M3Error.m3 >>> >>> 0x37f26c 0xdd4401 RecordError + 0x2e8 in ..\src\toolmisc\M3Error.m3 >>> >>> 0x37f298 0xdd4026 Report + 0x23 in ..\src\toolmisc\M3Error.m3 >>> >>> 0x37f308 0xe46703 Eval + 0x220 in ..\src\sem\M3CExpValue.m3 >>> >>> 0x37f358 0xe48773 Set + 0x672 in ..\src\sem\M3CExpValue.m3 >>> >>> 0x37f380 0xda645b DoVisit + 0x121 in ..\src\gast\ASTWalk.m3 >>> >>> 0x37f3a4 0xe381de Range + 0x85 in ..\src\ast\M3AST_AS_Walk.m3 >>> >>> 0x37f3c8 0xda63e8 DoVisit + 0xae in ..\src\gast\ASTWalk.m3 >>> >>> 0x37f3ec 0xe36a81 Subrange_type + 0x85 in ..\src\ast\M3AST_AS_Walk.m3 >>> >>> 0x37f410 0xda63e8 DoVisit + 0xae in ..\src\gast\ASTWalk.m3 >>> >>> ......... ......... ... more frames ... >>> >>> "C:\cm3\pkg\netobj\src\netobj.tmpl", line 37: quake runtime error: exit 2147 >> 483647: C:\cm3\bin\stubgen -v1 -sno RemoteView.T -T.M3IMPTAB >>> >>> --procedure-- -line- -file--- >>> >>> exec -- >>> >>> _v_netobj 37 C:\cm3\pkg\netobj\src\netobj.tmpl >>> >>> netobjv1 44 C:\cm3\pkg\netobj\src\netobj.tmpl >>> >>> netobj 64 C:\cm3\pkg\netobj\src\netobj.tmpl >>> >>> include_dir 105 C:\cm3\Sandbox\m3-ui\juno-2\juno-app\src\m3makefile >>> >>> 4 C:\cm3\Sandbox\m3-ui\juno-2\juno-app\NT386\m3make.args >>> >>> Fatal Error: package build failed >>> >>> WARNING: Encountered an error when processing package "m3-ui\juno-2\juno-app >> " for "-build". >>> >>> Regards, >>> >>> Randy Coleburn >>> From rodney_bates at lcwb.coop Tue May 17 23:47:08 2011 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Tue, 17 May 2011 16:47:08 -0500 Subject: [M3devel] LONGINT -> more bugs in m3tk In-Reply-To: <4DB6F2B2.3090905@lcwb.coop> References: <20110419115106.7E6A31A207A@async.async.caltech.edu> <4DB6F2B2.3090905@lcwb.coop> Message-ID: <4DD2ECDC.8070806@lcwb.coop> Mika, can you tell me what main program and command you used to get these errors? It would help me to test changes to m3tk. On 04/26/2011 11:28 AM, Rodney M. Bates wrote: > I just checked in a patch tp M3CExpValue.m3 in m3tk, in the head, which I believe will fix this > bug. I compiled it, but have not tested it, as I am sure Mika has this case to retry > more quickly than I can. > > On 04/19/2011 06:51 AM, Mika Nystrom wrote: >> Hello m3devel, >> >> If anyone knows how to fix the following trivially, please go ahead. >> >> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,45: type error in arguments to binary operator >> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,25: bad numeric literal >> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,51: bad numeric literal >> >> (errors reported by m3tk). >> >> The offending line is: >> >> INTERFACE BasicCtypes; >> >> IMPORT Word, Long; >> >> TYPE >> (* the four signed integer types *) >> signed_char = [-16_7f-1 .. 16_7f]; >> short_int = [-16_7fff-1 .. 16_7fff]; >> int = [-16_7fffffff-1 .. 16_7fffffff]; >> long_int = [-16_7fffffffffffffff -1 .. 16_7fffffffffffffff ]; >> long_long = [-16_7fffffffffffffffL-1L .. 16_7fffffffffffffffL]; (** HERE **) >> >> (* the four unsigned integer types *) >> unsigned_char = [16_0 .. 16_ff]; >> unsigned_short_int = [16_0 .. 16_ffff]; >> unsigned_int = [16_0 .. 16_ffffffff]; >> unsigned_long_int = Word.T; >> unsigned_long_long = Long.T; >> >> (* the three floating types *) >> float = REAL; >> double = LONGREAL; >> long_double = EXTENDED; >> >> (* char *) >> char = signed_char; >> >> END BasicCtypes. >> >> I'll look at it myself, but not immediately (no time). Workaround for now. >> >> Mika >> > From mika at async.caltech.edu Wed May 18 03:35:42 2011 From: mika at async.caltech.edu (Mika Nystrom) Date: Tue, 17 May 2011 18:35:42 -0700 Subject: [M3devel] LONGINT -> more bugs in m3tk In-Reply-To: <4DD2ECDC.8070806@lcwb.coop> References: <20110419115106.7E6A31A207A@async.async.caltech.edu> <4DB6F2B2.3090905@lcwb.coop> <4DD2ECDC.8070806@lcwb.coop> Message-ID: <20110518013542.194111A2078@async.async.caltech.edu> I think you'll get that error if you run stubgen on anything that references a type from BasicCtypes (e.g., int, char_star ...) I'm pretty sure I actually got it running the stub generator for my Scheme interpreter, which I have posted links to here a few times, but I haven't had time to push into CM3 yet. Mika "Rodney M. Bates" writes: >Mika, can you tell me what main program and command you used to get these erro >rs? >It would help me to test changes to m3tk. > >On 04/26/2011 11:28 AM, Rodney M. Bates wrote: >> I just checked in a patch tp M3CExpValue.m3 in m3tk, in the head, which I be >lieve will fix this >> bug. I compiled it, but have not tested it, as I am sure Mika has this case >to retry >> more quickly than I can. >> >> On 04/19/2011 06:51 AM, Mika Nystrom wrote: >>> Hello m3devel, >>> >>> If anyone knows how to fix the following trivially, please go ahead. >>> >>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,45: type e >rror in arguments to binary operator >>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,25: bad nu >meric literal >>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,51: bad nu >meric literal >>> >>> (errors reported by m3tk). >>> >>> The offending line is: >>> >>> INTERFACE BasicCtypes; >>> >>> IMPORT Word, Long; >>> >>> TYPE >>> (* the four signed integer types *) >>> signed_char = [-16_7f-1 .. 16_7f]; >>> short_int = [-16_7fff-1 .. 16_7fff]; >>> int = [-16_7fffffff-1 .. 16_7fffffff]; >>> long_int = [-16_7fffffffffffffff -1 .. 16_7fffffffffffffff ]; >>> long_long = [-16_7fffffffffffffffL-1L .. 16_7fffffffffffffffL]; (** HERE ** >) >>> >>> (* the four unsigned integer types *) >>> unsigned_char = [16_0 .. 16_ff]; >>> unsigned_short_int = [16_0 .. 16_ffff]; >>> unsigned_int = [16_0 .. 16_ffffffff]; >>> unsigned_long_int = Word.T; >>> unsigned_long_long = Long.T; >>> >>> (* the three floating types *) >>> float = REAL; >>> double = LONGREAL; >>> long_double = EXTENDED; >>> >>> (* char *) >>> char = signed_char; >>> >>> END BasicCtypes. >>> >>> I'll look at it myself, but not immediately (no time). Workaround for now. >>> >>> Mika >>> >> From rcolebur at SCIRES.COM Wed May 18 20:27:44 2011 From: rcolebur at SCIRES.COM (Coleburn, Randy) Date: Wed, 18 May 2011 14:27:44 -0400 Subject: [M3devel] LONGINT -> more bugs in m3tk In-Reply-To: <20110518013542.194111A2078@async.async.caltech.edu> References: <20110419115106.7E6A31A207A@async.async.caltech.edu> <4DB6F2B2.3090905@lcwb.coop> <4DD2ECDC.8070806@lcwb.coop> <20110518013542.194111A2078@async.async.caltech.edu> Message-ID: While we are on the subject of the stub generator, there is another long-standing problem. I've submitted this one years ago and I think I still have the example program I devised to show it. So, I'll try to dig this up and put it into the bug tracker. The basic situation is that there are cases where the stub generator doesn't generate imports for all interfaces needed by the resulting stub. You can work around this problem by manually editing the generated stub to provide the missing imports, but this gets old quickly. I'll send a follow-up post with the details once I find them in my archives. Regards, Randy Coleburn -----Original Message----- From: Mika Nystrom [mailto:mika at async.caltech.edu] Sent: Tuesday, May 17, 2011 9:36 PM To: Rodney M. Bates Cc: m3devel at elegosoft.com Subject: Re: [M3devel] LONGINT -> more bugs in m3tk I think you'll get that error if you run stubgen on anything that references a type from BasicCtypes (e.g., int, char_star ...) I'm pretty sure I actually got it running the stub generator for my Scheme interpreter, which I have posted links to here a few times, but I haven't had time to push into CM3 yet. Mika "Rodney M. Bates" writes: >Mika, can you tell me what main program and command you used to get these erro >rs? >It would help me to test changes to m3tk. > >On 04/26/2011 11:28 AM, Rodney M. Bates wrote: >> I just checked in a patch tp M3CExpValue.m3 in m3tk, in the head, which I be >lieve will fix this >> bug. I compiled it, but have not tested it, as I am sure Mika has this case >to retry >> more quickly than I can. >> >> On 04/19/2011 06:51 AM, Mika Nystrom wrote: >>> Hello m3devel, >>> >>> If anyone knows how to fix the following trivially, please go ahead. >>> >>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,45: type e >rror in arguments to binary operator >>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,25: bad nu >meric literal >>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,51: bad nu >meric literal >>> >>> (errors reported by m3tk). >>> >>> The offending line is: >>> >>> INTERFACE BasicCtypes; >>> >>> IMPORT Word, Long; >>> >>> TYPE >>> (* the four signed integer types *) >>> signed_char = [-16_7f-1 .. 16_7f]; >>> short_int = [-16_7fff-1 .. 16_7fff]; >>> int = [-16_7fffffff-1 .. 16_7fffffff]; >>> long_int = [-16_7fffffffffffffff -1 .. 16_7fffffffffffffff ]; >>> long_long = [-16_7fffffffffffffffL-1L .. 16_7fffffffffffffffL]; (** HERE ** >) >>> >>> (* the four unsigned integer types *) >>> unsigned_char = [16_0 .. 16_ff]; >>> unsigned_short_int = [16_0 .. 16_ffff]; >>> unsigned_int = [16_0 .. 16_ffffffff]; >>> unsigned_long_int = Word.T; >>> unsigned_long_long = Long.T; >>> >>> (* the three floating types *) >>> float = REAL; >>> double = LONGREAL; >>> long_double = EXTENDED; >>> >>> (* char *) >>> char = signed_char; >>> >>> END BasicCtypes. >>> >>> I'll look at it myself, but not immediately (no time). Workaround for now. >>> >>> Mika >>> >> From rcolebur at SCIRES.COM Wed May 18 23:04:41 2011 From: rcolebur at SCIRES.COM (Coleburn, Randy) Date: Wed, 18 May 2011 17:04:41 -0400 Subject: [M3devel] LONGINT -> more bugs in m3tk In-Reply-To: References: <20110419115106.7E6A31A207A@async.async.caltech.edu> <4DB6F2B2.3090905@lcwb.coop> <4DD2ECDC.8070806@lcwb.coop> <20110518013542.194111A2078@async.async.caltech.edu> Message-ID: Ok, I found some stuff in my archives about a set of documented stubgen problems, but this stuff doesn't include the problem I described with the failure to generate imports for all interfaces. Actually, I think this interface import problem is with the network objects stub generator, so I will either find or create an example of this problem and submit later. Here is a short program (with comments) that demonstrates some stubgen problems. I generated this program back in January 2001, so these are long-standing issues. Regards, Randy Coleburn m3makefile is: import("libm3") import("netobj") Interface("StubGenProblem") Netobj("StubGenProblem", "T") Library("NetObjProblem") StubGenProblem.i3 is: INTERFACE StubGenProblem; (* Interface demonstrating problem with Network Objects Stub Generator *) (* R.C.Coleburn, 01/24/2001 *) IMPORT NetObj, Thread; TYPE MyRecord = RECORD a: INTEGER := 0; b: TEXT := "zero"; END; CONST Default = MyRecord{1, "one"}; TYPE MyObject = OBJECT myRec: MyRecord := Default; (* if you change above line to be: myRec: MyRecord; that is, leave out the default initializer, the stub generator no longer complains when parameters of type MyObject are passed to methods of type T. *) END; TYPE T = NetObj.T OBJECT METHODS (* method testA is accepted by the NetObj Stub Generator *) testA(myRec: MyRecord) RAISES {NetObj.Error, Thread.Alerted}; (* method testB is accepted by the NetObj Stub Generator *) testB(myRec: MyRecord := Default) RAISES {NetObj.Error, Thread.Alerted}; (* method testC yeilds the following error from the NetObj Stub Generator: stubgen: INTERNAL ERROR: AstToVal.ProcessExp: unsupported value *) (* Does anyone know why the stub generator can't handle this? *) (* Does anyone know of a workaround or a fix to the stub generator? *) testC(myObj: MyObject) RAISES {NetObj.Error, Thread.Alerted}; (* BTW, if you comment out the assignment of Default to MyObject.myRec in the declaration on line 16, the stub generator no longer complains. So, it seems that the problem is passing an object parameter containing a record field member with a default initializer. Note that passing a record parameter with a default initializer is not a problem for the stub generator. *) END; END StubGenProblem. -----Original Message----- From: Coleburn, Randy Sent: Wednesday, May 18, 2011 2:28 PM To: Mika Nystrom; Rodney M. Bates Cc: m3devel at elegosoft.com Subject: Re: [M3devel] LONGINT -> more bugs in m3tk While we are on the subject of the stub generator, there is another long-standing problem. I've submitted this one years ago and I think I still have the example program I devised to show it. So, I'll try to dig this up and put it into the bug tracker. The basic situation is that there are cases where the stub generator doesn't generate imports for all interfaces needed by the resulting stub. You can work around this problem by manually editing the generated stub to provide the missing imports, but this gets old quickly. I'll send a follow-up post with the details once I find them in my archives. Regards, Randy Coleburn From dabenavidesd at yahoo.es Wed May 18 23:49:05 2011 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Wed, 18 May 2011 22:49:05 +0100 (BST) Subject: [M3devel] LONGINT -> more bugs in m3tk In-Reply-To: Message-ID: <846840.19495.qm@web29712.mail.ird.yahoo.com> Hi all: This is good news (though old) shows up, this is perhaps the problem with Obliq problem (worked in pm3), by the way what could be missing if so from there in CM3? Thanks in advance PS It might be that CM3 once worked Obliq, since there is a thesis reportedly working on Obliq3D of Blair MacIntyre, an augmented reality system, this is probably 1999, so a lot of stuff might came or not after that. --- El mi?, 18/5/11, Coleburn, Randy escribi?: > De: Coleburn, Randy > Asunto: Re: [M3devel] LONGINT -> more bugs in m3tk > Para: "m3devel at elegosoft.com" > Fecha: mi?rcoles, 18 de mayo, 2011 16:04 > Ok, I found some stuff in my archives > about a set of documented stubgen problems, but this stuff > doesn't include the problem I described with the failure to > generate imports for all interfaces. Actually, I think > this interface import problem is with the network objects > stub generator, so I will either find or create an example > of this problem and submit later. > > Here is a short program (with comments) that demonstrates > some stubgen problems. I generated this program back > in January 2001, so these are long-standing issues. > > Regards, > Randy Coleburn > > > m3makefile is: > > import("libm3") > import("netobj") > Interface("StubGenProblem") > Netobj("StubGenProblem", "T") > Library("NetObjProblem") > > > > StubGenProblem.i3 is: > > INTERFACE StubGenProblem; > (* Interface demonstrating problem with Network Objects > Stub Generator *) > (* R.C.Coleburn, 01/24/2001 *) > IMPORT > NetObj, > Thread; > TYPE > MyRecord = RECORD > a: INTEGER := 0; > b: TEXT := "zero"; > END; > CONST > Default = MyRecord{1, "one"}; > TYPE > MyObject = OBJECT > myRec: MyRecord := Default; > (* if you change above line to be: > myRec: MyRecord; > that is, leave out > the default initializer, the stub > generator no longer > complains when parameters of type > MyObject are passed > to methods of type T. *) > END; > TYPE > T = NetObj.T OBJECT > METHODS > (* method testA is accepted by the > NetObj Stub Generator *) > testA(myRec: MyRecord) RAISES > {NetObj.Error, Thread.Alerted}; > > (* method testB is accepted by the > NetObj Stub Generator *) > testB(myRec: MyRecord := Default) > RAISES {NetObj.Error, Thread.Alerted}; > > (* method testC yeilds the following > error from the NetObj Stub Generator: > stubgen: INTERNAL > ERROR: AstToVal.ProcessExp: unsupported value *) > (* Does anyone know why the stub > generator can't handle this? *) > (* Does anyone know of a workaround or > a fix to the stub generator? *) > testC(myObj: MyObject) RAISES > {NetObj.Error, Thread.Alerted}; > > (* BTW, if you comment out the > assignment of Default to MyObject.myRec > in the declaration on line 16, the > stub generator no longer complains. > So, it seems that the problem is > passing an object parameter containing > a record field member with a default > initializer. Note that passing a > record parameter with a default > initializer is not a problem for the > stub generator. *) > END; > END StubGenProblem. > > > > -----Original Message----- > From: Coleburn, Randy > Sent: Wednesday, May 18, 2011 2:28 PM > To: Mika Nystrom; Rodney M. Bates > Cc: m3devel at elegosoft.com > Subject: Re: [M3devel] LONGINT -> more bugs in m3tk > > While we are on the subject of the stub generator, there is > another long-standing problem. > > I've submitted this one years ago and I think I still have > the example program I devised to show it. > > So, I'll try to dig this up and put it into the bug > tracker. > > The basic situation is that there are cases where the stub > generator doesn't generate imports for all interfaces needed > by the resulting stub. You can work around this > problem by manually editing the generated stub to provide > the missing imports, but this gets old quickly. > > I'll send a follow-up post with the details once I find > them in my archives. > > Regards, > Randy Coleburn > From mika at async.caltech.edu Thu May 19 01:38:58 2011 From: mika at async.caltech.edu (Mika Nystrom) Date: Wed, 18 May 2011 16:38:58 -0700 Subject: [M3devel] LONGINT -> more bugs in m3tk In-Reply-To: References: <20110419115106.7E6A31A207A@async.async.caltech.edu> <4DB6F2B2.3090905@lcwb.coop> <4DD2ECDC.8070806@lcwb.coop> <20110518013542.194111A2078@async.async.caltech.edu> Message-ID: <20110518233858.545FB1A2078@async.async.caltech.edu> Ah, ok... such bugs ought to be fairly easy to fix. Maybe... To be clear, there are at least three stub generators that use m3tk that I know of (and probably others too) "stubgen" for Network Objects "stablegen" for some sort of stable storage database "sstubgen" (not in CM3 yet!) that generates stubs for the "Modula-Scheme system" (what I referenced below) Mika "Coleburn, Randy" writes: >While we are on the subject of the stub generator, there is another long-st= >anding problem. > >I've submitted this one years ago and I think I still have the example prog= >ram I devised to show it. > >So, I'll try to dig this up and put it into the bug tracker. > >The basic situation is that there are cases where the stub generator doesn'= >t generate imports for all interfaces needed by the resulting stub. You ca= >n work around this problem by manually editing the generated stub to provid= >e the missing imports, but this gets old quickly. > >I'll send a follow-up post with the details once I find them in my archives= >. > >Regards, >Randy Coleburn > >-----Original Message----- >From: Mika Nystrom [mailto:mika at async.caltech.edu]=20 >Sent: Tuesday, May 17, 2011 9:36 PM >To: Rodney M. Bates >Cc: m3devel at elegosoft.com >Subject: Re: [M3devel] LONGINT -> more bugs in m3tk > >I think you'll get that error if you run stubgen on anything that reference= >s >a type from BasicCtypes (e.g., int, char_star ...) > >I'm pretty sure I actually got it running the stub generator for my >Scheme interpreter, which I have posted links to here a few times, but I >haven't had time to push into CM3 yet. > > Mika > >"Rodney M. Bates" writes: >>Mika, can you tell me what main program and command you used to get these = >erro >>rs? >>It would help me to test changes to m3tk. >> >>On 04/26/2011 11:28 AM, Rodney M. Bates wrote: >>> I just checked in a patch tp M3CExpValue.m3 in m3tk, in the head, which = >I be >>lieve will fix this >>> bug. I compiled it, but have not tested it, as I am sure Mika has this c= >ase=20 >>to retry >>> more quickly than I can. >>> >>> On 04/19/2011 06:51 AM, Mika Nystrom wrote: >>>> Hello m3devel, >>>> >>>> If anyone knows how to fix the following trivially, please go ahead. >>>> >>>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,45: ty= >pe e >>rror in arguments to binary operator >>>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,25: ba= >d nu >>meric literal >>>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,51: ba= >d nu >>meric literal >>>> >>>> (errors reported by m3tk). >>>> >>>> The offending line is: >>>> >>>> INTERFACE BasicCtypes; >>>> >>>> IMPORT Word, Long; >>>> >>>> TYPE >>>> (* the four signed integer types *) >>>> signed_char =3D [-16_7f-1 .. 16_7f]; >>>> short_int =3D [-16_7fff-1 .. 16_7fff]; >>>> int =3D [-16_7fffffff-1 .. 16_7fffffff]; >>>> long_int =3D [-16_7fffffffffffffff -1 .. 16_7fffffffffffffff ]; >>>> long_long =3D [-16_7fffffffffffffffL-1L .. 16_7fffffffffffffffL]; (** H= >ERE ** >>) >>>> >>>> (* the four unsigned integer types *) >>>> unsigned_char =3D [16_0 .. 16_ff]; >>>> unsigned_short_int =3D [16_0 .. 16_ffff]; >>>> unsigned_int =3D [16_0 .. 16_ffffffff]; >>>> unsigned_long_int =3D Word.T; >>>> unsigned_long_long =3D Long.T; >>>> >>>> (* the three floating types *) >>>> float =3D REAL; >>>> double =3D LONGREAL; >>>> long_double =3D EXTENDED; >>>> >>>> (* char *) >>>> char =3D signed_char; >>>> >>>> END BasicCtypes. >>>> >>>> I'll look at it myself, but not immediately (no time). Workaround for n= >ow. >>>> >>>> Mika >>>> >>> From rodney_bates at lcwb.coop Wed May 18 23:41:31 2011 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Wed, 18 May 2011 16:41:31 -0500 Subject: [M3devel] LONGINT -> more bugs in m3tk In-Reply-To: <20110518013542.194111A2078@async.async.caltech.edu> References: <20110419115106.7E6A31A207A@async.async.caltech.edu> <4DB6F2B2.3090905@lcwb.coop> <4DD2ECDC.8070806@lcwb.coop> <20110518013542.194111A2078@async.async.caltech.edu> Message-ID: <4DD43D0B.6080400@lcwb.coop> Thanks. That got me going. On 05/17/2011 08:35 PM, Mika Nystrom wrote: > I think you'll get that error if you run stubgen on anything that references > a type from BasicCtypes (e.g., int, char_star ...) > > I'm pretty sure I actually got it running the stub generator for my > Scheme interpreter, which I have posted links to here a few times, but I > haven't had time to push into CM3 yet. > > Mika > > "Rodney M. Bates" writes: >> Mika, can you tell me what main program and command you used to get these erro >> rs? >> It would help me to test changes to m3tk. >> >> On 04/26/2011 11:28 AM, Rodney M. Bates wrote: >>> I just checked in a patch tp M3CExpValue.m3 in m3tk, in the head, which I be >> lieve will fix this >>> bug. I compiled it, but have not tested it, as I am sure Mika has this case >> to retry >>> more quickly than I can. >>> >>> On 04/19/2011 06:51 AM, Mika Nystrom wrote: >>>> Hello m3devel, >>>> >>>> If anyone knows how to fix the following trivially, please go ahead. >>>> >>>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,45: type e >> rror in arguments to binary operator >>>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,25: bad nu >> meric literal >>>> "/usr/local/cm3/pkg/m3core/src/C/64BITS/BasicCtypes.i3", line 18,51: bad nu >> meric literal >>>> >>>> (errors reported by m3tk). >>>> >>>> The offending line is: >>>> >>>> INTERFACE BasicCtypes; >>>> >>>> IMPORT Word, Long; >>>> >>>> TYPE >>>> (* the four signed integer types *) >>>> signed_char = [-16_7f-1 .. 16_7f]; >>>> short_int = [-16_7fff-1 .. 16_7fff]; >>>> int = [-16_7fffffff-1 .. 16_7fffffff]; >>>> long_int = [-16_7fffffffffffffff -1 .. 16_7fffffffffffffff ]; >>>> long_long = [-16_7fffffffffffffffL-1L .. 16_7fffffffffffffffL]; (** HERE ** >> ) >>>> >>>> (* the four unsigned integer types *) >>>> unsigned_char = [16_0 .. 16_ff]; >>>> unsigned_short_int = [16_0 .. 16_ffff]; >>>> unsigned_int = [16_0 .. 16_ffffffff]; >>>> unsigned_long_int = Word.T; >>>> unsigned_long_long = Long.T; >>>> >>>> (* the three floating types *) >>>> float = REAL; >>>> double = LONGREAL; >>>> long_double = EXTENDED; >>>> >>>> (* char *) >>>> char = signed_char; >>>> >>>> END BasicCtypes. >>>> >>>> I'll look at it myself, but not immediately (no time). Workaround for now. >>>> >>>> Mika >>>> >>> > From rodney_bates at lcwb.coop Thu May 19 17:41:15 2011 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Thu, 19 May 2011 10:41:15 -0500 Subject: [M3devel] missing libm3/src/types Message-ID: <4DD53A1B.3030805@lcwb.coop> What happened to cm3/m3-libs/libm3/src/types and its contents in the head? They all are gone, but cm3/m3-libs/libm3/src/m3makefile contains include_dir ("types"), and libm3 won't build: rodney at allegheny:~/proj/m3/cm3-new/cm3/scripts$ ./do-pkg.sh build libm3 /home/rodney/proj/m3/cm3-new/cm3/scripts/pkgmap.sh -c "cm3 -build -override $RARGS -DROOT='/home/rodney/proj/m3/cm3-new/cm3' " libm3 === package /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3 === +++ cm3 -build -override $RARGS -DROOT='/home/rodney/proj/m3/cm3-new/cm3' +++ --- building in AMD64_LINUX --- "/home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/m3makefile", line 27: quake runtime error: unable to open "/home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/types/m3makefile" for reading --procedure-- -line- -file--- include_dir -- include_dir 27 /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/m3makefile 6 /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/AMD64_LINUX/m3make.args Fatal Error: package build failed ==> /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3 done rodney at allegheny:~/proj/m3/cm3-new/cm3/scripts$ It looks like either types needs to come back, or include_dir ("types") needs to go away, but which? If somebody knows, it would save a lot of time poking around. From hosking at cs.purdue.edu Thu May 19 17:45:59 2011 From: hosking at cs.purdue.edu (Tony Hosking) Date: Thu, 19 May 2011 11:45:59 -0400 Subject: [M3devel] missing libm3/src/types In-Reply-To: <4DD53A1B.3030805@lcwb.coop> References: <4DD53A1B.3030805@lcwb.coop> Message-ID: <3169D748-68A3-4A9A-A582-60C68D32AB94@cs.purdue.edu> Moved to m3core. There shouldn't be anything in libm3/types. On May 19, 2011, at 11:41 AM, Rodney M. Bates wrote: > What happened to cm3/m3-libs/libm3/src/types and its contents in the head? > They all are gone, but cm3/m3-libs/libm3/src/m3makefile contains > include_dir ("types"), and libm3 won't build: > > > rodney at allegheny:~/proj/m3/cm3-new/cm3/scripts$ ./do-pkg.sh build libm3 > /home/rodney/proj/m3/cm3-new/cm3/scripts/pkgmap.sh -c "cm3 -build -override $RARGS -DROOT='/home/rodney/proj/m3/cm3-new/cm3' " libm3 > === package /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3 === > +++ cm3 -build -override $RARGS -DROOT='/home/rodney/proj/m3/cm3-new/cm3' +++ > --- building in AMD64_LINUX --- > > "/home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/m3makefile", line 27: quake runtime error: unable to open "/home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/types/m3makefile" for reading > > --procedure-- -line- -file--- > include_dir -- > include_dir 27 /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/m3makefile > 6 /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/AMD64_LINUX/m3make.args > > Fatal Error: package build failed > ==> /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3 done > > rodney at allegheny:~/proj/m3/cm3-new/cm3/scripts$ > > It looks like either types needs to come back, or include_dir ("types") needs to go away, > but which? If somebody knows, it would save a lot of time poking around. From hosking at cs.purdue.edu Thu May 19 17:51:36 2011 From: hosking at cs.purdue.edu (Tony Hosking) Date: Thu, 19 May 2011 11:51:36 -0400 Subject: [M3devel] missing libm3/src/types In-Reply-To: <3169D748-68A3-4A9A-A582-60C68D32AB94@cs.purdue.edu> References: <4DD53A1B.3030805@lcwb.coop> <3169D748-68A3-4A9A-A582-60C68D32AB94@cs.purdue.edu> Message-ID: <55EDF7AD-B04C-48DF-9266-7A3B3A61CDCF@cs.purdue.edu> Actually, looks like Jay tried to restore LongrealType and RealType for Mika. Clients should really be adjusted to include: IMPORT LongFloat as LongrealType, RealFloat as RealType; On May 19, 2011, at 11:45 AM, Tony Hosking wrote: > Moved to m3core. There shouldn't be anything in libm3/types. > > On May 19, 2011, at 11:41 AM, Rodney M. Bates wrote: > >> What happened to cm3/m3-libs/libm3/src/types and its contents in the head? >> They all are gone, but cm3/m3-libs/libm3/src/m3makefile contains >> include_dir ("types"), and libm3 won't build: >> >> >> rodney at allegheny:~/proj/m3/cm3-new/cm3/scripts$ ./do-pkg.sh build libm3 >> /home/rodney/proj/m3/cm3-new/cm3/scripts/pkgmap.sh -c "cm3 -build -override $RARGS -DROOT='/home/rodney/proj/m3/cm3-new/cm3' " libm3 >> === package /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3 === >> +++ cm3 -build -override $RARGS -DROOT='/home/rodney/proj/m3/cm3-new/cm3' +++ >> --- building in AMD64_LINUX --- >> >> "/home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/m3makefile", line 27: quake runtime error: unable to open "/home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/types/m3makefile" for reading >> >> --procedure-- -line- -file--- >> include_dir -- >> include_dir 27 /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/m3makefile >> 6 /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/AMD64_LINUX/m3make.args >> >> Fatal Error: package build failed >> ==> /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3 done >> >> rodney at allegheny:~/proj/m3/cm3-new/cm3/scripts$ >> >> It looks like either types needs to come back, or include_dir ("types") needs to go away, >> but which? If somebody knows, it would save a lot of time poking around. > From dabenavidesd at yahoo.es Thu May 19 18:18:20 2011 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Thu, 19 May 2011 17:18:20 +0100 (BST) Subject: [M3devel] missing libm3/src/types In-Reply-To: <3169D748-68A3-4A9A-A582-60C68D32AB94@cs.purdue.edu> Message-ID: <321796.84407.qm@web29715.mail.ird.yahoo.com> Hi all: if it could affect the compiler usage if in fact such usage why would one give such types inside cm3 or m3build process aside of m3core, I mean the top hierarchy must be primitive types at bottom then refs, objects, etc or reverse, and its type rules besides modules and interfaces, perhaps a good example would be to see the interfaces of Modula-2+ Vulcan system, since it had everything compiled cached and managed to survive even crashes and bridge everything to the Vesta CM system, quick large compilations, see: http://www-cs-faculty.stanford.edu/~eroberts/cv.html An advanced system to type check may require quick timely access to large nodes since type inference is something very dependent on its size, a bigger tree a bigger problem, even if ever get to compile type inferencing (an Obliq prototype already done), but many modules around would be like dancing in hard feet over sized. Thanks in advance --- El jue, 19/5/11, Tony Hosking escribi?: > De: Tony Hosking > Asunto: Re: [M3devel] missing libm3/src/types > Para: "Rodney M. Bates" > CC: "m3devel" > Fecha: jueves, 19 de mayo, 2011 10:45 > Moved to m3core. There > shouldn't be anything in libm3/types. > > On May 19, 2011, at 11:41 AM, Rodney M. Bates wrote: > > > What happened to cm3/m3-libs/libm3/src/types and its > contents in the head? > > They all are gone, but > cm3/m3-libs/libm3/src/m3makefile contains > > include_dir ("types"), and libm3 won't build: > > > > > > rodney at allegheny:~/proj/m3/cm3-new/cm3/scripts$ > ./do-pkg.sh build libm3 > > /home/rodney/proj/m3/cm3-new/cm3/scripts/pkgmap.sh -c > "cm3 -build -override $RARGS > -DROOT='/home/rodney/proj/m3/cm3-new/cm3' " libm3 > > === package > /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3 === > > +++ cm3 -build -override $RARGS > -DROOT='/home/rodney/proj/m3/cm3-new/cm3' +++ > > --- building in AMD64_LINUX --- > > > > > "/home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/m3makefile", > line 27: quake runtime error: unable to open > "/home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/types/m3makefile" > for reading > > > > --procedure-- -line- -file--- > > include_dir -- > > > include_dir 27 > /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/src/m3makefile > > > 6 > /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3/AMD64_LINUX/m3make.args > > > > Fatal Error: package build failed > > ==> /home/rodney/proj/m3/cm3-new/cm3/m3-libs/libm3 > done > > > > rodney at allegheny:~/proj/m3/cm3-new/cm3/scripts$ > > > > It looks like either types needs to come back, or > include_dir ("types") needs to go away, > > but which? If somebody knows, it would save a > lot of time poking around. > > From jay.krell at cornell.edu Sun May 22 10:26:30 2011 From: jay.krell at cornell.edu (Jay K) Date: Sun, 22 May 2011 08:26:30 +0000 Subject: [M3devel] range analysis? Message-ID: I've been sitting on this diff a long while. In some places the frontend knows the bounds of a type/value and will optimize away range checks. I'm pretty sure. This makes it do that more. I haven't looked at or tested this in ages. But the basic idea seems sound, simple, easy enough to get a few small wins from. For example if you have: a: [-10..-1]; b: [1..10]; then all comparisons between a and b are compile-time constant. Comparisons of cardinals to negative numbers, likewise. One thing maybe missing below is handling of empty ranges like a: [1..-1]; The code assumes the minimum of a type is less than or equal to its maximum. Index: m3-sys/m3front/src/misc/CG.i3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.i3,v retrieving revision 1.15 diff -r1.15 CG.i3 11c11 < IMPORT Target, M3CG, M3; --- > IMPORT Target, M3CG, M3, TInt; 402c402,406 < PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type); --- > PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type; > min_valid: BOOLEAN := FALSE; > max_valid: BOOLEAN := FALSE; > min: Target.Int := TInt.Zero; > max: Target.Int := TInt.Zero); 414,415c418,423 < PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0); < (* == Load (v, o, t.size, t.align, t) *) --- > PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0; > min_valid: BOOLEAN := FALSE; > max_valid: BOOLEAN := FALSE; > min: Target.Int := TInt.Zero; > max: Target.Int := TInt.Zero); > (* == Load (v, o, t.size, t.align, t, min/max...) *) Index: m3-sys/m3front/src/misc/CG.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.m3,v retrieving revision 1.40 diff -r1.40 CG.m3 13c13 < IMPORT M3, M3CG, M3CG_Ops, M3CG_Check; --- > IMPORT M3, M3CG, M3CG_Ops, M3CG_Check, RTIO, RTParams; 45a46,49 > min_valid : BOOLEAN := FALSE; (* whether or not min is valid *) > max_valid : BOOLEAN := FALSE; (* whether or not max is valid *) > min : Target.Int := TInt.Zero; (* the minimum possible value *) > max : Target.Int := TInt.Zero; (* the maximum possible value *) 80c84,85 < VAR --- > VAR > debug := FALSE; 604a610,614 > v.min := TInt.Zero; > v.max := TInt.Zero; > v.min_valid := FALSE; > v.max_valid := FALSE; > 766a777,780 > x.min := TInt.Zero; > x.max := TInt.Zero; > x.min_valid := FALSE; > x.max_valid := FALSE; 978a993,995 > IF debug THEN > RTIO.PutText("m3front:cg:Init_int:NOT in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); > END; 980a998,1001 > END; > > IF debug THEN > RTIO.PutText("m3front:cg:Init_int:in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); 1266c1287,1291 < PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type) = --- > PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type; > min_valid: BOOLEAN := FALSE; > max_valid: BOOLEAN := FALSE; > min: Target.Int := TInt.Zero; > max: Target.Int := TInt.Zero) = 1276c1301 < SimpleLoad (v, o, t); --- > SimpleLoad (v, o, t, min_valid, max_valid, min, max); 1291c1316 < SimpleLoad (v, o, best_type); --- > SimpleLoad (v, o, best_type, min_valid, max_valid, min, max); 1312c1337,1341 < PROCEDURE SimpleLoad (v: Var; o: Offset; t: Type) = --- > PROCEDURE SimpleLoad (v: Var; o: Offset; t: Type; > min_valid: BOOLEAN := FALSE; > max_valid: BOOLEAN := FALSE; > min: Target.Int := TInt.Zero; > max: Target.Int := TInt.Zero) = 1323a1353,1356 > x.min_valid := min_valid; > x.max_valid := max_valid; > x.min := min; > x.max := max; 1339a1373,1376 > x.min := TInt.Zero; > x.max := TInt.Zero; > x.min_valid := FALSE; > x.max_valid := FALSE; 1347a1385,1388 > stack[tos-1].min := TInt.Zero; > stack[tos-1].max := TInt.Zero; > stack[tos-1].min_valid := FALSE; > stack[tos-1].max_valid := FALSE; 1350c1391,1395 < PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0) = --- > PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0; > min_valid: BOOLEAN := FALSE; > max_valid: BOOLEAN := FALSE; > min: Target.Int := TInt.Zero; > max: Target.Int := TInt.Zero) = 1352c1397 < SimpleLoad (v, o, t); --- > SimpleLoad (v, o, t, min_valid, max_valid, min, max); 1815a1861,1864 > x.min_valid := TRUE; > x.max_valid := TRUE; > x.min := i; > x.max := i; 1832,1834c1881,2007 < BEGIN < IF Force_pair (commute := TRUE) THEN < op := M3CG.SwappedCompare [op]; --- > VAR always_true: BOOLEAN; > always_false: BOOLEAN; > left_type: Type; > right_type: Type; > left_min: Target.Int; > left_max: Target.Int; > right_min: Target.Int; > right_max: Target.Int; > left_signed: BOOLEAN; > right_signed: BOOLEAN; > BEGIN > > always_true := FALSE; > always_false := FALSE; > > WITH left = stack [SCheck (2, "Compare-left")], > right = stack [SCheck (1, "Compare-right")] DO > > left_type := left.type; > right_type := right.type; > > IF left.min_valid > AND left.max_valid > AND right.min_valid > AND right.max_valid > AND Target.OrdinalType[left_type] > AND Target.OrdinalType[right_type] THEN > > left_min := left.min; > left_max := left.max; > right_min := right.min; > right_max := right.max; > left_signed := Target.SignedType[left_type]; > right_signed := Target.SignedType[right_type]; > > (* First handle types that match in signedness. *) > > IF left_signed = right_signed THEN > > (* Check for ranges with no overlap. *) > > IF left_signed (* and right_signed *) THEN > IF TInt.LT(left_max, right_min) THEN > always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; > ELSIF TInt.GT(left_min, right_max) THEN > always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; > END; > ELSE (* left_signed and right_signed both false *) > IF TWord.LT(left_max, right_min) THEN > always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; > ELSIF TWord.GT(left_min, right_max) THEN > always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; > END; > END; > > (* Check for overlap just on the edge, e.g. [0..1] compared to [1..2]. *) > > IF NOT (always_true OR always_false) THEN > IF TInt.EQ(left_max, right_min) THEN > always_true := op = Cmp.LE; > always_false := op = Cmp.GT; > ELSIF TInt.EQ(left_min, right_max) THEN > always_true := op = Cmp.GE; > always_false := op = Cmp.LT; > END; > END; > > (* Handle equal subranges with one element, not likely to occur. *) > > IF NOT (always_true OR always_false) THEN > IF TInt.EQ(left_max, left_min) > AND TInt.EQ(left_max, right_max) > AND TInt.EQ(left_max, right_min) THEN > always_true := op IN SET OF Cmp{Cmp.GE, Cmp.LE, Cmp.EQ}; > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.GT, Cmp.NE}; > END; > END; > ELSE > > (* Now deal with mixed up types (signed compared to unsigned). > * We may be able to merge these by setting some min/max > * to zero. That is, the minimum of an unsigned type is zero. > * However we want to be sure not to interpret unsigned min/max > * as signed. > *) > > IF left_signed THEN > IF TInt.LT(left_max, TInt.Zero) THEN > always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; > ELSIF TInt.EQ(left_max, TInt.Zero) THEN > always_true := op = Cmp.LE; > always_false := op = Cmp.GT; > END; > ELSE (* right is signed *) > IF TInt.LT(right_max, TInt.Zero) THEN > always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; > ELSIF TInt.EQ(right_max, TInt.Zero) THEN > always_true := op = Cmp.GE; > always_false := op = Cmp.LT; > END; > END; > END; > END; > > <* ASSERT NOT (always_true AND always_false) *> > > IF always_true OR always_false THEN > Discard(right_type); > Discard(left_type); > IF always_true THEN > cg.load_integer (Target.Integer.cg_type, TInt.One); > ELSE > cg.load_integer (Target.Integer.cg_type, TInt.Zero); > END > ELSE > IF Force_pair (commute := TRUE) THEN > op := M3CG.SwappedCompare [op]; > END; > cg.compare (t, Target.Integer.cg_type, op); > SPop (2, "Compare"); > END; 1836,1837d2008 < cg.compare (t, Target.Integer.cg_type, op); < SPop (2, "Compare"); 2880a3052,3055 > x.min := TInt.Zero; > x.max := TInt.Zero; > x.min_valid := FALSE; > x.max_valid := FALSE; 2977c3152,3153 < BEGIN --- > BEGIN > debug := debug OR RTParams.IsPresent ("m3front_cg_debug"); Index: m3-sys/m3front/src/values/Variable.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/values/Variable.m3,v retrieving revision 1.13 diff -r1.13 Variable.m3 362a363,365 > VAR min: Target.Int; > max: Target.Int; > bounds_valid: BOOLEAN; 395c398,401 < CG.Load (t.cg_var, t.offset, t.size, t.cg_align, t.stk_type); --- > (*GetBounds (t, min, max); > bounds_valid := TInt.LE(min, max);*) > bounds_valid := t.tipe # NIL AND Type.GetBounds(t.tipe, min, max) AND TInt.LE(min, max); > CG.Load (t.cg_var, t.offset, t.size, t.cg_align, t.stk_type, bounds_valid, bounds_valid, min, max); -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Sun May 22 10:58:50 2011 From: jay.krell at cornell.edu (Jay K) Date: Sun, 22 May 2011 08:58:50 +0000 Subject: [M3devel] thread tester on 32bit Windows Message-ID: I'm not sure if I posted this. This is on Windows XP. C:\dev2\cm3.2\m3-libs\m3core\tests\thread>\bin\x86\cdb NT386\threadtest.exe @M3paranoidgc Microsoft (R) Windows Debugger Version 6.11.0001.404 X86 Copyright (c) Microsoft Corporation. All rights reserved. CommandLine: NT386\threadtest.exe @M3paranoidgc Symbol search path is: SRV*C:\symbols*http://msdl.microsoft.com/download/symbols Executable search path is: ModLoad: 00400000 00c7b000 threadtest.exe ModLoad: 7c900000 7c9b2000 ntdll.dll ModLoad: 7c800000 7c8f6000 C:\WINDOWS2\system32\kernel32.dll ModLoad: 78520000 785c3000 C:\WINDOWS2\WinSxS\x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.30729.4974_x-ww_d889290f\MSVCR90.dll (6ec.1010): Break instruction exception - code 80000003 (first chance) eax=00251eb4 ebx=7ffdf000 ecx=00000005 edx=00000020 esi=00251f48 edi=00251eb4 eip=7c90120e esp=0012fb20 ebp=0012fc94 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202 ntdll!DbgBreakPoint: 7c90120e cc int 3 0:000> .lines Line number information will be loaded 0:000> g Writing file...done Creating read threads...done Creating fork threads...done Creating alloc threads...done Creating lock threads...done running...printing oldest/median age/newest .(6ec.116c): Access violation - code c0000005 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=001ffffc ebx=00200000 ecx=00000002 edx=004317f0 esi=00380018 edi=00380018 eip=0043181c esp=0117fb98 ebp=0117fbc0 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010202 threadtest!RTCollector__RefSanityCheck+0x2c: 0043181c 8b18 mov ebx,dword ptr [eax] ds:0023:001ffffc=???????? 0:005> db @eax 001ffffc ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 0020000c ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 0020001c ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 0020002c ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 0020003c ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 0020004c ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 0020005c ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 0020006c ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 0:005> ~*k 0 Id: 6ec.1010 Suspend: 2 Teb: 7ffde000 Unfrozen ChildEBP RetAddr 0012fcd8 7c90d21a ntdll!KiFastSystemCallRet 0012fcdc 7c8023f1 ntdll!NtDelayExecution+0xc 0012fd34 7c802455 kernel32!SleepEx+0x61 0012fd44 0042bd6e kernel32!Sleep+0xf 0012fd84 0042bb47 threadtest!ThreadWin32__XPause+0x1c7 [..\src\thread\WIN32\ThreadWin32.m3 @ 765] 0012fda8 00404870 threadtest!Thread__Pause+0x31 [..\src\thread\WIN32\ThreadWin32.m3 @ 727] 0012fee4 00426c95 threadtest!Main_M3+0x13e2 [..\src\Main.m3 @ 558] 0012ff28 00426262 threadtest!RTLinker__RunMainBody+0x250 [..\src\runtime\common\RTLinker.m3 @ 406] 0012ff40 00426306 threadtest!RTLinker__AddUnitI+0xf7 [..\src\runtime\common\RTLinker.m3 @ 113] 0012ff60 00401038 threadtest!RTLinker__AddUnit+0x9c [..\src\runtime\common\RTLinker.m3 @ 122] 0012ff7c 00462900 threadtest!main+0x38 [_m3main.mc @ 4] 0012ffc0 7c817077 threadtest!__tmainCRTStartup+0x10f [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 582] 0012fff0 00000000 kernel32!BaseProcessStart+0x23 1 Id: 6ec.1168 Suspend: 2 Teb: 7ffdd000 Unfrozen ChildEBP RetAddr 00d7fc64 7c90df5a ntdll!KiFastSystemCallRet 00d7fc68 7c919b23 ntdll!NtWaitForSingleObject+0xc 00d7fcf0 7c901046 ntdll!RtlpWaitForCriticalSection+0x132 00d7fcf8 0042a153 ntdll!RtlEnterCriticalSection+0x46 00d7fd30 0042a830 threadtest!ThreadWin32__InitCondition+0xa1 [..\src\thread\WIN32\ThreadWin32.m3 @ 186] 00d7fd50 0042cc08 threadtest!Thread__Broadcast+0x3f [..\src\thread\WIN32\ThreadWin32.m3 @ 409] 00d7fd6c 004295f9 threadtest!RTOS__UnlockHeap+0xb3 [..\src\thread\WIN32\ThreadWin32.m3 @ 1181] 00d7fd88 00429586 threadtest!RTAllocator_M3_LINE_370+0x15 [..\src\runtime\common\RTAllocator.m3 @ 371] 00d7fdc8 00428ba8 threadtest!RTAllocator__AllocTraced+0x105 [..\src\runtime\common\RTAllocator.m3 @ 368] 00d7fdfc 004286dc threadtest!RTAllocator__GetTracedObj+0x86 [..\src\runtime\common\RTAllocator.m3 @ 224] 00d7fe18 00408679 threadtest!RTHooks__AllocateTracedObj+0x15 [..\src\runtime\common\RTAllocator.m3 @ 122] 00d7fe40 00401360 threadtest!FileRd__Open+0x19 [..\src\rw\FileRd.m3 @ 16] 00d7ff78 0042b5ff threadtest!Main__RApply+0x160 [..\src\Main.m3 @ 182] 00d7ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ThreadWin32.m3 @ 615] 00d7ffec 00000000 kernel32!BaseThreadStart+0x37 2 Id: 6ec.1174 Suspend: 2 Teb: 7ffdc000 Unfrozen ChildEBP RetAddr 00e7fc64 7c90df5a ntdll!KiFastSystemCallRet 00e7fc68 7c919b23 ntdll!NtWaitForSingleObject+0xc 00e7fcf0 7c901046 ntdll!RtlpWaitForCriticalSection+0x132 00e7fcf8 0042a153 ntdll!RtlEnterCriticalSection+0x46 00e7fd30 0042a830 threadtest!ThreadWin32__InitCondition+0xa1 [..\src\thread\WIN32\ThreadWin32.m3 @ 186] 00e7fd50 0042cc08 threadtest!Thread__Broadcast+0x3f [..\src\thread\WIN32\ThreadWin32.m3 @ 409] 00e7fd6c 004295f9 threadtest!RTOS__UnlockHeap+0xb3 [..\src\thread\WIN32\ThreadWin32.m3 @ 1181] 00e7fd88 00429586 threadtest!RTAllocator_M3_LINE_370+0x15 [..\src\runtime\common\RTAllocator.m3 @ 371] 00e7fdc8 00428ba8 threadtest!RTAllocator__AllocTraced+0x105 [..\src\runtime\common\RTAllocator.m3 @ 368] 00e7fdfc 004286dc threadtest!RTAllocator__GetTracedObj+0x86 [..\src\runtime\common\RTAllocator.m3 @ 224] 00e7fe18 00408679 threadtest!RTHooks__AllocateTracedObj+0x15 [..\src\runtime\common\RTAllocator.m3 @ 122] 00e7fe40 00401360 threadtest!FileRd__Open+0x19 [..\src\rw\FileRd.m3 @ 16] 00e7ff78 0042b5ff threadtest!Main__RApply+0x160 [..\src\Main.m3 @ 182] 00e7ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ThreadWin32.m3 @ 615] 00e7ffec 00000000 kernel32!BaseThreadStart+0x37 3 Id: 6ec.14cc Suspend: 2 Teb: 7ffdb000 Unfrozen ChildEBP RetAddr 00f7fd1c 7c90d0ba ntdll!KiFastSystemCallRet 00f7fd20 7c8109b6 ntdll!NtCreateFile+0xc 00f7fdb8 7c801a53 kernel32!CreateFileW+0x35f 00f7fddc 00417f10 kernel32!CreateFileA+0x30 00f7fe18 00408689 threadtest!FS__OpenFileReadonly+0x3c [..\src\os\WIN32\FSWin32.m3 @ 226] 00f7fe40 00401360 threadtest!FileRd__Open+0x29 [..\src\rw\FileRd.m3 @ 16] 00f7ff78 0042b5ff threadtest!Main__RApply+0x160 [..\src\Main.m3 @ 182] 00f7ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ ThreadWin32.m3 @ 615] 00f7ffec 00000000 kernel32!BaseThreadStart+0x37 4 Id: 6ec.d20 Suspend: 2 Teb: 7ffda000 Unfrozen ChildEBP RetAddr 0107fcf8 7c90df5a ntdll!KiFastSystemCallRet 0107fcfc 7c919b23 ntdll!NtWaitForSingleObject+0xc 0107fd84 7c901046 ntdll!RtlpWaitForCriticalSection+0x132 0107fd8c 0042cb42 ntdll!RtlEnterCriticalSection+0x46 0107fda0 0042954e threadtest!RTOS__LockHeap+0x2c [..\src\thread\WIN32\ThreadWin32.m3 @ 1168] 0107fde0 00428ba8 threadtest!RTAllocator__AllocTraced+0xcd [..\src\runtime\common\RTAllocator.m3 @ 367] 0107fe14 004286dc threadtest!RTAllocator__GetTracedObj+0x86 [..\src\runtime\common\RTAllocator.m3 @ 224] 0107fe30 00452f79 threadtest!RTHooks__AllocateTracedObj+0x15 [..\src\runtime\common\RTAllocator.m3 @ 122] 0107fe4c 0043e62a threadtest!Text8CString__New+0x19 [..\src\text\Text8CString.m3 @ 17] 0107fe64 0043cdf3 threadtest!M3toC__StoT+0x16 [..\src\C\Common\M3toC.m3 @ 96] 0107fe90 0040d037 threadtest!RTArgs__GetArg+0x6e [..\src\runtime\WIN32\RTArgs.m3 @ 139] 0107feb8 00401d6a threadtest!Params__Get+0x57 [..\src\params\Params.m3 @ 18] 0107ff78 0042b5ff threadtest!Main__FApply+0x141 [..\src\Main.m3 @ 245] 0107ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ThreadWin32.m3 @ 615] 0107ffec 00000000 kernel32!BaseThreadStart+0x37 # 5 Id: 6ec.116c Suspend: 1 Teb: 7ffd9000 Unfrozen ChildEBP RetAddr 0117fbc0 0044fbdc threadtest!RTCollector__RefSanityCheck+0x2c [..\src\runtime\common\RTCollector.m3 @ 1702] 0117fc04 0044f4df threadtest!RTHeapMap__Walk+0x448 [..\src\runtime\common\RTHeapMap.m3 @ 202] 0117fc28 0044f4ba threadtest!RTHeapMap__DoWalkRef+0x62 [..\src\runtime\common\RTHeapMap.m3 @ 62] 0117fc4c 0044f4ba threadtest!RTHeapMap__DoWalkRef+0x3d [..\src\runtime\common\RTHeapMap.m3 @ 57] 0117fc70 0044f475 threadtest!RTHeapMap__DoWalkRef+0x3d [..\src\runtime\common\RTHeapMap.m3 @ 57] 0117fc9c 00431607 threadtest!RTHeapMap__WalkRef+0xf5 [..\src\runtime\common\RTHeapMap.m3 @ 47] 0117fcd8 0044eab4 threadtest!RTCollector__SanityCheck+0x23c [..\src\runtime\common\RTCollector.m3 @ 1660] 0117fcf8 0042f379 threadtest!RTHeapRep__InvokeMonitors+0x84 [..\src\runtime\common\RTHeapRep.m3 @ 56] 0117fd4c 0042f15e threadtest!RTCollector__CollectSomeInStateZero+0x1e0 [..\src\runtime\common\RTCollector.m3 @ 786] 0117fd5c 0042edfc threadtest!RTCollector__CollectSome+0x6e [..\src\runtime\common\RTCollector.m3 @ 720] 0117fda0 00429554 threadtest!RTHeapRep__CollectEnough+0x9b [..\src\runtime\common\RTCollector.m3 @ 655] 0117fde0 00428ba8 threadtest!RTAllocator__AllocTraced+0xd3 [..\src\runtime\common\RTAllocator.m3 @ 368] 0117fe14 004286dc threadtest!RTAllocator__GetTracedObj+0x86 [..\src\runtime\common\RTAllocator.m3 @ 224] 0117fe30 00452f79 threadtest!RTHooks__AllocateTracedObj+0x15 [..\src\runtime\common\RTAllocator.m3 @ 122] 0117fe4c 0043e62a threadtest!Text8CString__New+0x19 [..\src\text\Text8CString.m3 @ 17] 0117fe64 0043cdf3 threadtest!M3toC__StoT+0x16 [..\src\C\Common\M3toC.m3 @ 96] 0117fe90 0040d037 threadtest!RTArgs__GetArg+0x6e [..\src\runtime\WIN32\RTArgs.m3 @ 139] 0117feb8 00401d6a threadtest!Params__Get+0x57 [..\src\params\Params.m3 @ 18] 0117ff78 0042b5ff threadtest!Main__FApply+0x141 [..\src\Main.m3 @ 245] 0117ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ThreadWin32.m3 @ 615] 6 Id: 6ec.11b4 Suspend: 2 Teb: 7ffd8000 Unfrozen ChildEBP RetAddr 0127fcf8 7c90df5a ntdll!KiFastSystemCallRet 0127fcfc 7c919b23 ntdll!NtWaitForSingleObject+0xc 0127fd84 7c901046 ntdll!RtlpWaitForCriticalSection+0x132 0127fd8c 0042cb42 ntdll!RtlEnterCriticalSection+0x46 0127fda0 0042954e threadtest!RTOS__LockHeap+0x2c [..\src\thread\WIN32\ThreadWin32.m3 @ 1168] 0127fde0 00428ba8 threadtest!RTAllocator__AllocTraced+0xcd [..\src\runtime\common\RTAllocator.m3 @ 367] 0127fe14 004286dc threadtest!RTAllocator__GetTracedObj+0x86 [..\src\runtime\common\RTAllocator.m3 @ 224] 0127fe30 00452f79 threadtest!RTHooks__AllocateTracedObj+0x15 [..\src\runtime\common\RTAllocator.m3 @ 122] 0127fe4c 0043e62a threadtest!Text8CString__New+0x19 [..\src\text\Text8CString.m3 @ 17] 0127fe64 0043cdf3 threadtest!M3toC__StoT+0x16 [..\src\C\Common\M3toC.m3 @ 96] 0127fe90 0040d037 threadtest!RTArgs__GetArg+0x6e [..\src\runtime\WIN32\RTArgs.m3 @ 139] 0127feb8 00401d6a threadtest!Params__Get+0x57 [..\src\params\Params.m3 @ 18] 0127ff78 0042b5ff threadtest!Main__FApply+0x141 [..\src\Main.m3 @ 245] 0127ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ThreadWin32.m3 @ 615] 0127ffec 00000000 kernel32!BaseThreadStart+0x37 7 Id: 6ec.1038 Suspend: 2 Teb: 7ffd7000 Unfrozen ChildEBP RetAddr 0137fdd4 7c90df5a ntdll!KiFastSystemCallRet 0137fdd8 7c919b23 ntdll!NtWaitForSingleObject+0xc 0137fe60 7c901046 ntdll!RtlpWaitForCriticalSection+0x132 0137fe68 0042cb42 ntdll!RtlEnterCriticalSection+0x46 0137fe7c 0042954e threadtest!RTOS__LockHeap+0x2c [..\src\thread\WIN32\ThreadWin32.m3 @ 1168] 0137febc 004290fd threadtest!RTAllocator__AllocTraced+0xcd [..\src\runtime\common\RTAllocator.m3 @ 367] 0137fef8 00428788 threadtest!RTAllocator__GetOpenArray+0x91 [..\src\runtime\common\RTAllocator.m3 @ 296] 0137ff1c 00402430 threadtest!RTHooks__AllocateOpenArray+0x19 [..\src\runtime\common\RTAllocator.m3 @ 143] 0137ff78 0042b5ff threadtest!Main__AApply+0x128 [..\src\Main.m3 @ 283] 0137ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ThreadWin32.m3 @ 615] 0137ffec 00000000 kernel32!BaseThreadStart+0x37 8 Id: 6ec.1034 Suspend: 2 Teb: 7ffd6000 Unfrozen ChildEBP RetAddr 0147fdd4 7c90df5a ntdll!KiFastSystemCallRet 0147fdd8 7c919b23 ntdll!NtWaitForSingleObject+0xc 0147fe60 7c901046 ntdll!RtlpWaitForCriticalSection+0x132 0147fe68 0042cb42 ntdll!RtlEnterCriticalSection+0x46 0147fe7c 0042954e threadtest!RTOS__LockHeap+0x2c [..\src\thread\WIN32\ThreadWin32.m3 @ 1168] 0147febc 004290fd threadtest!RTAllocator__AllocTraced+0xcd [..\src\runtime\common\RTAllocator.m3 @ 367] 0147fef8 00428788 threadtest!RTAllocator__GetOpenArray+0x91 [..\src\runtime\common\RTAllocator.m3 @ 296] 0147ff1c 00402430 threadtest!RTHooks__AllocateOpenArray+0x19 [..\src\runtime\common\RTAllocator.m3 @ 143] 0147ff78 0042b5ff threadtest!Main__AApply+0x128 [..\src\Main.m3 @ 283] 0147ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ThreadWin32.m3 @ 615] 0147ffec 00000000 kernel32!BaseThreadStart+0x37 9 Id: 6ec.10d0 Suspend: 2 Teb: 7ffd5000 Unfrozen ChildEBP RetAddr 0157fdd4 7c90df5a ntdll!KiFastSystemCallRet 0157fdd8 7c919b23 ntdll!NtWaitForSingleObject+0xc 0157fe60 7c901046 ntdll!RtlpWaitForCriticalSection+0x132 0157fe68 0042cb42 ntdll!RtlEnterCriticalSection+0x46 0157fe7c 0042954e threadtest!RTOS__LockHeap+0x2c [..\src\thread\WIN32\ThreadWin32.m3 @ 1168] 0157febc 004290fd threadtest!RTAllocator__AllocTraced+0xcd [..\src\runtime\common\RTAllocator.m3 @ 367] 0157fef8 00428788 threadtest!RTAllocator__GetOpenArray+0x91 [..\src\runtime\common\RTAllocator.m3 @ 296] 0157ff1c 00402430 threadtest!RTHooks__AllocateOpenArray+0x19 [..\src\runtime\common\RTAllocator.m3 @ 143] 0157ff78 0042b5ff threadtest!Main__AApply+0x128 [..\src\Main.m3 @ 283] 0157ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ThreadWin32.m3 @ 615] 0157ffec 00000000 kernel32!BaseThreadStart+0x37 10 Id: 6ec.ff8 Suspend: 2 Teb: 7ffd4000 Unfrozen ChildEBP RetAddr 0167fe48 7c90df5a ntdll!KiFastSystemCallRet 0167fe4c 7c919b23 ntdll!NtWaitForSingleObject+0xc 0167fed4 7c901046 ntdll!RtlpWaitForCriticalSection+0x132 0167fedc 00429f52 ntdll!RtlEnterCriticalSection+0x46 0167ff10 0042a287 threadtest!ThreadWin32__InitMutex+0x53 [..\src\thread\WIN32\ThreadWin32.m3 @ 148] 0167ff28 00402a5f threadtest!ThreadWin32__LockMutex+0x3f [..\src\thread\WIN32\ThreadWin32.m3 @ 210] 0167ff78 0042b5ff threadtest!Main__LApply+0x15f [..\src\Main.m3 @ 319] 0167ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ThreadWin32.m3 @ 615] 0167ffec 00000000 kernel32!BaseThreadStart+0x37 11 Id: 6ec.10e8 Suspend: 2 Teb: 7ffaf000 Unfrozen ChildEBP RetAddr 0177fdfc 7c90df5a ntdll!KiFastSystemCallRet 0177fe00 7c919b23 ntdll!NtWaitForSingleObject+0xc 0177fe88 7c901046 ntdll!RtlpWaitForCriticalSection+0x132 0177fe90 0042cb42 ntdll!RtlEnterCriticalSection+0x46 0177fea4 004332ce threadtest!RTOS__LockHeap+0x2c [..\src\thread\WIN32\ThreadWin2.m3 @ 1168] 0177fed8 00429faf threadtest!RTHeapRep__RegisterFinalCleanup+0x73 [..\src\runtime\common\RTCollector.m3 @ 2150] 0177ff10 0042a287 threadtest!ThreadWin32__InitMutex+0xb0 [..\src\thread\WIN32\ThreadWin32.m3 @ 156] 0177ff28 00402a5f threadtest!ThreadWin32__LockMutex+0x3f [..\src\thread\WIN32\ThreadWin32.m3 @ 210] 0177ff78 0042b5ff threadtest!Main__LApply+0x15f [..\src\Main.m3 @ 319] 0177ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ThreadWin32.m3 @ 615] 0177ffec 00000000 kernel32!BaseThreadStart+0x37 12 Id: 6ec.10d8 Suspend: 2 Teb: 7ffae000 Unfrozen ChildEBP RetAddr 0187fe48 7c90df5a ntdll!KiFastSystemCallRet 0187fe4c 7c919b23 ntdll!NtWaitForSingleObject+0xc 0187fed4 7c901046 ntdll!RtlpWaitForCriticalSection+0x132 0187fedc 00429f52 ntdll!RtlEnterCriticalSection+0x46 0187ff10 0042a287 threadtest!ThreadWin32__InitMutex+0x53 [..\src\thread\WIN32\ThreadWin32.m3 @ 148] 0187ff28 00402a5f threadtest!ThreadWin32__LockMutex+0x3f [..\src\thread\WIN32\ThreadWin32.m3 @ 210] 0187ff78 0042b5ff threadtest!Main__LApply+0x15f [..\src\Main.m3 @ 319] 0187ffb4 7c80b729 threadtest!ThreadWin32__ThreadBase+0x254 [..\src\thread\WIN32\ThreadWin32.m3 @ 615] 0187ffec 00000000 kernel32!BaseThreadStart+0x37 0:005> I suspect more logging/tracing is needed, to see what was moved where. - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Sun May 22 20:51:08 2011 From: hosking at cs.purdue.edu (Tony Hosking) Date: Sun, 22 May 2011 14:51:08 -0400 Subject: [M3devel] range analysis? In-Reply-To: References: Message-ID: <7FF8F0BA-AEC4-40DB-98A0-E1206985A72E@cs.purdue.edu> This is problematic. On May 22, 2011, at 4:26 AM, Jay K wrote: > The code assumes the minimum of a type is less than or equal to its maximum. -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Sun May 22 20:51:59 2011 From: hosking at cs.purdue.edu (Tony Hosking) Date: Sun, 22 May 2011 14:51:59 -0400 Subject: [M3devel] range analysis? In-Reply-To: References: Message-ID: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> So, one question is: what benefit does this really give? Your examples seem a little contrived. On May 22, 2011, at 4:26 AM, Jay K wrote: > I've been sitting on this diff a long while. > > In some places the frontend knows the bounds of a type/value and > will optimize away range checks. I'm pretty sure. > > > > This makes it do that more. > > > I haven't looked at or tested this in ages. > But the basic idea seems sound, simple, easy enough to get a few small wins from. > > For example if you have: > > a: [-10..-1]; > b: [1..10]; > > then all comparisons between a and b are compile-time constant. > > Comparisons of cardinals to negative numbers, likewise. > > One thing maybe missing below is handling of empty ranges like > a: [1..-1]; > > The code assumes the minimum of a type is less than or equal to its maximum. > > > Index: m3-sys/m3front/src/misc/CG.i3 > =================================================================== > RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.i3,v > retrieving revision 1.15 > diff -r1.15 CG.i3 > 11c11 > < IMPORT Target, M3CG, M3; > --- > > IMPORT Target, M3CG, M3, TInt; > 402c402,406 > < PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type); > --- > > PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type; > > min_valid: BOOLEAN := FALSE; > > max_valid: BOOLEAN := FALSE; > > min: Target.Int := TInt.Zero; > > max: Target.Int := TInt.Zero); > 414,415c418,423 > < PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0); > < (* == Load (v, o, t.size, t.align, t) *) > --- > > PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0; > > min_valid: BOOLEAN := FALSE; > > max_valid: BOOLEAN := FALSE; > > min: Target.Int := TInt.Zero; > > max: Target.Int := TInt.Zero); > > (* == Load (v, o, t.size, t.align, t, min/max...) *) > Index: m3-sys/m3front/src/misc/CG.m3 > =================================================================== > RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.m3,v > retrieving revision 1.40 > diff -r1.40 CG.m3 > 13c13 > < IMPORT M3, M3CG, M3CG_Ops, M3CG_Check; > --- > > IMPORT M3, M3CG, M3CG_Ops, M3CG_Check, RTIO, RTParams; > 45a46,49 > > min_valid : BOOLEAN := FALSE; (* whether or not min is valid *) > > max_valid : BOOLEAN := FALSE; (* whether or not max is valid *) > > min : Target.Int := TInt.Zero; (* the minimum possible value *) > > max : Target.Int := TInt.Zero; (* the maximum possible value *) > 80c84,85 > < VAR > --- > > VAR > > debug := FALSE; > 604a610,614 > > v.min := TInt.Zero; > > v.max := TInt.Zero; > > v.min_valid := FALSE; > > v.max_valid := FALSE; > > > 766a777,780 > > x.min := TInt.Zero; > > x.max := TInt.Zero; > > x.min_valid := FALSE; > > x.max_valid := FALSE; > 978a993,995 > > IF debug THEN > > RTIO.PutText("m3front:cg:Init_int:NOT in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); > > END; > 980a998,1001 > > END; > > > > IF debug THEN > > RTIO.PutText("m3front:cg:Init_int:in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); > 1266c1287,1291 > < PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type) = > --- > > PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type; > > min_valid: BOOLEAN := FALSE; > > max_valid: BOOLEAN := FALSE; > > min: Target.Int := TInt.Zero; > > max: Target.Int := TInt.Zero) = > 1276c1301 > < SimpleLoad (v, o, t); > --- > > SimpleLoad (v, o, t, min_valid, max_valid, min, max); > 1291c1316 > < SimpleLoad (v, o, best_type); > --- > > SimpleLoad (v, o, best_type, min_valid, max_valid, min, max); > 1312c1337,1341 > < PROCEDURE SimpleLoad (v: Var; o: Offset; t: Type) = > --- > > PROCEDURE SimpleLoad (v: Var; o: Offset; t: Type; > > min_valid: BOOLEAN := FALSE; > > max_valid: BOOLEAN := FALSE; > > min: Target.Int := TInt.Zero; > > max: Target.Int := TInt.Zero) = > 1323a1353,1356 > > x.min_valid := min_valid; > > x.max_valid := max_valid; > > x.min := min; > > x.max := max; > 1339a1373,1376 > > x.min := TInt.Zero; > > x.max := TInt.Zero; > > x.min_valid := FALSE; > > x.max_valid := FALSE; > 1347a1385,1388 > > stack[tos-1].min := TInt.Zero; > > stack[tos-1].max := TInt.Zero; > > stack[tos-1].min_valid := FALSE; > > stack[tos-1].max_valid := FALSE; > 1350c1391,1395 > < PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0) = > --- > > PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0; > > min_valid: BOOLEAN := FALSE; > > max_valid: BOOLEAN := FALSE; > > min: Target.Int := TInt.Zero; > > max: Target.Int := TInt.Zero) = > 1352c1397 > < SimpleLoad (v, o, t); > --- > > SimpleLoad (v, o, t, min_valid, max_valid, min, max); > 1815a1861,1864 > > x.min_valid := TRUE; > > x.max_valid := TRUE; > > x.min := i; > > x.max := i; > 1832,1834c1881,2007 > < BEGIN > < IF Force_pair (commute := TRUE) THEN > < op := M3CG.SwappedCompare [op]; > --- > > VAR always_true: BOOLEAN; > > always_false: BOOLEAN; > > left_type: Type; > > right_type: Type; > > left_min: Target.Int; > > left_max: Target.Int; > > right_min: Target.Int; > > right_max: Target.Int; > > left_signed: BOOLEAN; > > right_signed: BOOLEAN; > > BEGIN > > > > always_true := FALSE; > > always_false := FALSE; > > > > WITH left = stack [SCheck (2, "Compare-left")], > > right = stack [SCheck (1, "Compare-right")] DO > > > > left_type := left.type; > > right_type := right.type; > > > > IF left.min_valid > > AND left.max_valid > > AND right.min_valid > > AND right.max_valid > > AND Target.OrdinalType[left_type] > > AND Target.OrdinalType[right_type] THEN > > > > left_min := left.min; > > left_max := left.max; > > right_min := right.min; > > right_max := right.max; > > left_signed := Target.SignedType[left_type]; > > right_signed := Target.SignedType[right_type]; > > > > (* First handle types that match in signedness. *) > > > > IF left_signed = right_signed THEN > > > > (* Check for ranges with no overlap. *) > > > > IF left_signed (* and right_signed *) THEN > > IF TInt.LT(left_max, right_min) THEN > > always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; > > always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; > > ELSIF TInt.GT(left_min, right_max) THEN > > always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; > > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; > > END; > > ELSE (* left_signed and right_signed both false *) > > IF TWord.LT(left_max, right_min) THEN > > always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; > > always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; > > ELSIF TWord.GT(left_min, right_max) THEN > > always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; > > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; > > END; > > END; > > > > (* Check for overlap just on the edge, e.g. [0..1] compared to [1..2]. *) > > > > IF NOT (always_true OR always_false) THEN > > IF TInt.EQ(left_max, right_min) THEN > > always_true := op = Cmp.LE; > > always_false := op = Cmp.GT; > > ELSIF TInt.EQ(left_min, right_max) THEN > > always_true := op = Cmp.GE; > > always_false := op = Cmp.LT; > > END; > > END; > > > > (* Handle equal subranges with one element, not likely to occur. *) > > > > IF NOT (always_true OR always_false) THEN > > IF TInt.EQ(left_max, left_min) > > AND TInt.EQ(left_max, right_max) > > AND TInt.EQ(left_max, right_min) THEN > > always_true := op IN SET OF Cmp{Cmp.GE, Cmp.LE, Cmp.EQ}; > > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.GT, Cmp.NE}; > > END; > > END; > > ELSE > > > > (* Now deal with mixed up types (signed compared to unsigned). > > * We may be able to merge these by setting some min/max > > * to zero. That is, the minimum of an unsigned type is zero. > > * However we want to be sure not to interpret unsigned min/max > > * as signed. > > *) > > > > IF left_signed THEN > > IF TInt.LT(left_max, TInt.Zero) THEN > > always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; > > always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; > > ELSIF TInt.EQ(left_max, TInt.Zero) THEN > > always_true := op = Cmp.LE; > > always_false := op = Cmp.GT; > > END; > > ELSE (* right is signed *) > > IF TInt.LT(right_max, TInt.Zero) THEN > > always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; > > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; > > ELSIF TInt.EQ(right_max, TInt.Zero) THEN > > always_true := op = Cmp.GE; > > always_false := op = Cmp.LT; > > END; > > END; > > END; > > END; > > > > <* ASSERT NOT (always_true AND always_false) *> > > > > IF always_true OR always_false THEN > > Discard(right_type); > > Discard(left_type); > > IF always_true THEN > > cg.load_integer (Target.Integer.cg_type, TInt.One); > > ELSE > > cg.load_integer (Target.Integer.cg_type, TInt.Zero); > > END > > ELSE > > IF Force_pair (commute := TRUE) THEN > > op := M3CG.SwappedCompare [op]; > > END; > > cg.compare (t, Target.Integer.cg_type, op); > > SPop (2, "Compare"); > > END; > 1836,1837d2008 > < cg.compare (t, Target.Integer.cg_type, op); > < SPop (2, "Compare"); > 2880a3052,3055 > > x.min := TInt.Zero; > > x.max := TInt.Zero; > > x.min_valid := FALSE; > > x.max_valid := FALSE; > 2977c3152,3153 > < BEGIN > --- > > BEGIN > > debug := debug OR RTParams.IsPresent ("m3front_cg_debug"); > Index: m3-sys/m3front/src/values/Variable.m3 > =================================================================== > RCS file: /usr/cvs/cm3/m3-sys/m3front/src/values/Variable.m3,v > retrieving revision 1.13 > diff -r1.13 Variable.m3 > 362a363,365 > > VAR min: Target.Int; > > max: Target.Int; > > bounds_valid: BOOLEAN; > 395c398,401 > < CG.Load (t.cg_var, t.offset, t.size, t.cg_align, t.stk_type); > --- > > (*GetBounds (t, min, max); > > bounds_valid := TInt.LE(min, max);*) > > bounds_valid := t.tipe # NIL AND Type.GetBounds(t.tipe, min, max) AND TInt.LE(min, max); > > CG.Load (t.cg_var, t.offset, t.size, t.cg_align, t.stk_type, bounds_valid, bounds_valid, min, max); > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Mon May 23 01:18:02 2011 From: jay.krell at cornell.edu (Jay K) Date: Sun, 22 May 2011 23:18:02 +0000 Subject: [M3devel] range analysis? In-Reply-To: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> References: , <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> Message-ID: Well, I can build the whole tree and see how many times it helps. I think this is a pretty standard optimization technique. Though it'd work better with compiler-derived additional information. I initially happened upon this idea developing test cases. > The code assumes the minimum of a type is less than or equal to its maximum. I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. - Jay Subject: Re: range analysis? From: hosking at cs.purdue.edu Date: Sun, 22 May 2011 14:51:59 -0400 CC: m3devel at elegosoft.com To: jay.krell at cornell.edu So, one question is: what benefit does this really give? Your examples seem a little contrived. On May 22, 2011, at 4:26 AM, Jay K wrote:I've been sitting on this diff a long while. In some places the frontend knows the bounds of a type/value and will optimize away range checks. I'm pretty sure. This makes it do that more. I haven't looked at or tested this in ages. But the basic idea seems sound, simple, easy enough to get a few small wins from. For example if you have: a: [-10..-1]; b: [1..10]; then all comparisons between a and b are compile-time constant. Comparisons of cardinals to negative numbers, likewise. One thing maybe missing below is handling of empty ranges like a: [1..-1]; The code assumes the minimum of a type is less than or equal to its maximum. Index: m3-sys/m3front/src/misc/CG.i3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.i3,v retrieving revision 1.15 diff -r1.15 CG.i3 11c11 < IMPORT Target, M3CG, M3; --- > IMPORT Target, M3CG, M3, TInt; 402c402,406 < PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type); --- > PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type; > min_valid: BOOLEAN := FALSE; > max_valid: BOOLEAN := FALSE; > min: Target.Int := TInt.Zero; > max: Target.Int := TInt.Zero); 414,415c418,423 < PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0); < (* == Load (v, o, t.size, t.align, t) *) --- > PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0; > min_valid: BOOLEAN := FALSE; > max_valid: BOOLEAN := FALSE; > min: Target.Int := TInt.Zero; > max: Target.Int := TInt.Zero); > (* == Load (v, o, t.size, t.align, t, min/max...) *) Index: m3-sys/m3front/src/misc/CG.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.m3,v retrieving revision 1.40 diff -r1.40 CG.m3 13c13 < IMPORT M3, M3CG, M3CG_Ops, M3CG_Check; --- > IMPORT M3, M3CG, M3CG_Ops, M3CG_Check, RTIO, RTParams; 45a46,49 > min_valid : BOOLEAN := FALSE; (* whether or not min is valid *) > max_valid : BOOLEAN := FALSE; (* whether or not max is valid *) > min : Target.Int := TInt.Zero; (* the minimum possible value *) > max : Target.Int := TInt.Zero; (* the maximum possible value *) 80c84,85 < VAR --- > VAR > debug := FALSE; 604a610,614 > v.min := TInt.Zero; > v.max := TInt.Zero; > v.min_valid := FALSE; > v.max_valid := FALSE; > 766a777,780 > x.min := TInt.Zero; > x.max := TInt.Zero; > x.min_valid := FALSE; > x.max_valid := FALSE; 978a993,995 > IF debug THEN > RTIO.PutText("m3front:cg:Init_int:NOT in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); > END; 980a998,1001 > END; > > IF debug THEN > RTIO.PutText("m3front:cg:Init_int:in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); 1266c1287,1291 < PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type) = --- > PROCEDURE Load (v: Var; o: Offset; s: Size; a: Alignment; t: Type; > min_valid: BOOLEAN := FALSE; > max_valid: BOOLEAN := FALSE; > min: Target.Int := TInt.Zero; > max: Target.Int := TInt.Zero) = 1276c1301 < SimpleLoad (v, o, t); --- > SimpleLoad (v, o, t, min_valid, max_valid, min, max); 1291c1316 < SimpleLoad (v, o, best_type); --- > SimpleLoad (v, o, best_type, min_valid, max_valid, min, max); 1312c1337,1341 < PROCEDURE SimpleLoad (v: Var; o: Offset; t: Type) = --- > PROCEDURE SimpleLoad (v: Var; o: Offset; t: Type; > min_valid: BOOLEAN := FALSE; > max_valid: BOOLEAN := FALSE; > min: Target.Int := TInt.Zero; > max: Target.Int := TInt.Zero) = 1323a1353,1356 > x.min_valid := min_valid; > x.max_valid := max_valid; > x.min := min; > x.max := max; 1339a1373,1376 > x.min := TInt.Zero; > x.max := TInt.Zero; > x.min_valid := FALSE; > x.max_valid := FALSE; 1347a1385,1388 > stack[tos-1].min := TInt.Zero; > stack[tos-1].max := TInt.Zero; > stack[tos-1].min_valid := FALSE; > stack[tos-1].max_valid := FALSE; 1350c1391,1395 < PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0) = --- > PROCEDURE Load_int (t: IType; v: Var; o: Offset := 0; > min_valid: BOOLEAN := FALSE; > max_valid: BOOLEAN := FALSE; > min: Target.Int := TInt.Zero; > max: Target.Int := TInt.Zero) = 1352c1397 < SimpleLoad (v, o, t); --- > SimpleLoad (v, o, t, min_valid, max_valid, min, max); 1815a1861,1864 > x.min_valid := TRUE; > x.max_valid := TRUE; > x.min := i; > x.max := i; 1832,1834c1881,2007 < BEGIN < IF Force_pair (commute := TRUE) THEN < op := M3CG.SwappedCompare [op]; --- > VAR always_true: BOOLEAN; > always_false: BOOLEAN; > left_type: Type; > right_type: Type; > left_min: Target.Int; > left_max: Target.Int; > right_min: Target.Int; > right_max: Target.Int; > left_signed: BOOLEAN; > right_signed: BOOLEAN; > BEGIN > > always_true := FALSE; > always_false := FALSE; > > WITH left = stack [SCheck (2, "Compare-left")], > right = stack [SCheck (1, "Compare-right")] DO > > left_type := left.type; > right_type := right.type; > > IF left.min_valid > AND left.max_valid > AND right.min_valid > AND right.max_valid > AND Target.OrdinalType[left_type] > AND Target.OrdinalType[right_type] THEN > > left_min := left.min; > left_max := left.max; > right_min := right.min; > right_max := right.max; > left_signed := Target.SignedType[left_type]; > right_signed := Target.SignedType[right_type]; > > (* First handle types that match in signedness. *) > > IF left_signed = right_signed THEN > > (* Check for ranges with no overlap. *) > > IF left_signed (* and right_signed *) THEN > IF TInt.LT(left_max, right_min) THEN > always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; > ELSIF TInt.GT(left_min, right_max) THEN > always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; > END; > ELSE (* left_signed and right_signed both false *) > IF TWord.LT(left_max, right_min) THEN > always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; > ELSIF TWord.GT(left_min, right_max) THEN > always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; > END; > END; > > (* Check for overlap just on the edge, e.g. [0..1] compared to [1..2]. *) > > IF NOT (always_true OR always_false) THEN > IF TInt.EQ(left_max, right_min) THEN > always_true := op = Cmp.LE; > always_false := op = Cmp.GT; > ELSIF TInt.EQ(left_min, right_max) THEN > always_true := op = Cmp.GE; > always_false := op = Cmp.LT; > END; > END; > > (* Handle equal subranges with one element, not likely to occur. *) > > IF NOT (always_true OR always_false) THEN > IF TInt.EQ(left_max, left_min) > AND TInt.EQ(left_max, right_max) > AND TInt.EQ(left_max, right_min) THEN > always_true := op IN SET OF Cmp{Cmp.GE, Cmp.LE, Cmp.EQ}; > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.GT, Cmp.NE}; > END; > END; > ELSE > > (* Now deal with mixed up types (signed compared to unsigned). > * We may be able to merge these by setting some min/max > * to zero. That is, the minimum of an unsigned type is zero. > * However we want to be sure not to interpret unsigned min/max > * as signed. > *) > > IF left_signed THEN > IF TInt.LT(left_max, TInt.Zero) THEN > always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; > ELSIF TInt.EQ(left_max, TInt.Zero) THEN > always_true := op = Cmp.LE; > always_false := op = Cmp.GT; > END; > ELSE (* right is signed *) > IF TInt.LT(right_max, TInt.Zero) THEN > always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; > always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; > ELSIF TInt.EQ(right_max, TInt.Zero) THEN > always_true := op = Cmp.GE; > always_false := op = Cmp.LT; > END; > END; > END; > END; > > <* ASSERT NOT (always_true AND always_false) *> > > IF always_true OR always_false THEN > Discard(right_type); > Discard(left_type); > IF always_true THEN > cg.load_integer (Target.Integer.cg_type, TInt.One); > ELSE > cg.load_integer (Target.Integer.cg_type, TInt.Zero); > END > ELSE > IF Force_pair (commute := TRUE) THEN > op := M3CG.SwappedCompare [op]; > END; > cg.compare (t, Target.Integer.cg_type, op); > SPop (2, "Compare"); > END; 1836,1837d2008 < cg.compare (t, Target.Integer.cg_type, op); < SPop (2, "Compare"); 2880a3052,3055 > x.min := TInt.Zero; > x.max := TInt.Zero; > x.min_valid := FALSE; > x.max_valid := FALSE; 2977c3152,3153 < BEGIN --- > BEGIN > debug := debug OR RTParams.IsPresent ("m3front_cg_debug"); Index: m3-sys/m3front/src/values/Variable.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/values/Variable.m3,v retrieving revision 1.13 diff -r1.13 Variable.m3 362a363,365 > VAR min: Target.Int; > max: Target.Int; > bounds_valid: BOOLEAN; 395c398,401 < CG.Load (t.cg_var, t.offset, t.size, t.cg_align, t.stk_type); --- > (*GetBounds (t, min, max); > bounds_valid := TInt.LE(min, max);*) > bounds_valid := t.tipe # NIL AND Type.GetBounds(t.tipe, min, max) AND TInt.LE(min, max); > CG.Load (t.cg_var, t.offset, t.size, t.cg_align, t.stk_type, bounds_valid, bounds_valid, min, max); -------------- next part -------------- An HTML attachment was scrubbed... URL: From hendrik at topoi.pooq.com Mon May 23 14:41:53 2011 From: hendrik at topoi.pooq.com (Hendrik Boom) Date: Mon, 23 May 2011 08:41:53 -0400 Subject: [M3devel] range analysis? In-Reply-To: References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> Message-ID: <20110523124153.GA31229@topoi.pooq.com> On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: > > Well, I can build the whole tree and see how many times it helps. > I think this is a pretty standard optimization technique. > Though it'd work better with compiler-derived additional information. > > I initially happened upon this idea developing test cases. > > > The code assumes the minimum of a type is less than or equal to its maximum. > > I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. What *is* the semantics of a range whose minimum is greater than its maximum? There plainly can't be any values in this range. How is a variable of this tyoe initialized? Not to some arbitrary value of the type, because there aren't any. I can see this type being useful to admit convenient generalizations -- for example, an array with n elements can still exist if n happens to be zero, but it seems to me that any code involving a value of the range for subscripts for this array must be simple unexecutable. Or is there some latitude available in the principle that a value of a variable must always be of the correct type? -- hendrik From hosking at cs.purdue.edu Mon May 23 16:31:24 2011 From: hosking at cs.purdue.edu (Tony Hosking) Date: Mon, 23 May 2011 10:31:24 -0400 Subject: [M3devel] range analysis? In-Reply-To: <20110523124153.GA31229@topoi.pooq.com> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> Message-ID: <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> An empty subrange gives a warning in the compiler. But, the semantics is that it is empty, and has no values of the type. You cannot allocate (NEW) an empty type. You cannot declare a field of empty type. Nor can you declare a variable of empty type. On May 23, 2011, at 8:41 AM, Hendrik Boom wrote: > On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: >> >> Well, I can build the whole tree and see how many times it helps. >> I think this is a pretty standard optimization technique. >> Though it'd work better with compiler-derived additional information. >> >> I initially happened upon this idea developing test cases. >> >>> The code assumes the minimum of a type is less than or equal to its maximum. >> >> I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. > > What *is* the semantics of a range whose minimum is greater than its > maximum? There plainly can't be any values in this range. How is a > variable of this tyoe initialized? Not to some arbitrary value of the > type, because there aren't any. I can see this type being useful to > admit convenient generalizations -- for example, an array with n > elements can still exist if n happens to be zero, but it seems to me > that any code involving a value of the range for subscripts for this > array must be simple unexecutable. > > Or is there some latitude available in the principle that a value of a > variable must always be of the correct type? > > -- hendrik From rodney_bates at lcwb.coop Mon May 23 18:45:14 2011 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Mon, 23 May 2011 11:45:14 -0500 Subject: [M3devel] range analysis? In-Reply-To: <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> Message-ID: <4DDA8F1A.3070207@lcwb.coop> On 05/23/2011 09:31 AM, Tony Hosking wrote: > An empty subrange gives a warning in the compiler. By my experiments, empty subrange, empty enumeration, and arrays thereof don't warn. > But, the semantics is that it is empty, and has no values of the type. > You cannot allocate (NEW) an empty type. > You cannot declare a field of empty type. It seems odd that we have this rule for fields, but no corresponding prohibition against arrays with empty element types. By experiments, cm3 allows this, for both fixed and open arrays, but treats such array types as empty types, something the language also does not say. At the least, the language and the compiler should agree with each other. Maybe records/objects and arrays should be treated consistently here? > Nor can you declare a variable of empty type. Again, oddly, there is no such prohibition in the language against declaring a formal parameter of empty type. Cm3 prohibits it, and calls it a 'variable' in the error message. Again, language and compiler should agree. The language also prohibits applying FIRST and LAST to the empty enumeration, but they are OK applied to an empty subrange. This makes sense, because they return values of the base type of the argument type, and such values exist for an empty subrange but not the empty enumeration, whose base type is only itself. > > On May 23, 2011, at 8:41 AM, Hendrik Boom wrote: > >> On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: >>> >>> Well, I can build the whole tree and see how many times it helps. >>> I think this is a pretty standard optimization technique. >>> Though it'd work better with compiler-derived additional information. >>> >>> I initially happened upon this idea developing test cases. >>> >>>> The code assumes the minimum of a type is less than or equal to its maximum. >>> >>> I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. >> >> What *is* the semantics of a range whose minimum is greater than its >> maximum? There plainly can't be any values in this range. How is a >> variable of this tyoe initialized? Not to some arbitrary value of the >> type, because there aren't any. I can see this type being useful to >> admit convenient generalizations -- for example, an array with n >> elements can still exist if n happens to be zero, but it seems to me >> that any code involving a value of the range for subscripts for this >> array must be simple unexecutable. >> >> Or is there some latitude available in the principle that a value of a >> variable must always be of the correct type? >> >> -- hendrik > > From hosking at cs.purdue.edu Mon May 23 18:54:36 2011 From: hosking at cs.purdue.edu (Tony Hosking) Date: Mon, 23 May 2011 12:54:36 -0400 Subject: [M3devel] range analysis? In-Reply-To: <4DDA8F1A.3070207@lcwb.coop> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> <4DDA8F1A.3070207@lcwb.coop> Message-ID: <8C9E1E77-686F-42E0-87FA-B573A4A02CC9@cs.purdue.edu> On May 23, 2011, at 12:45 PM, Rodney M. Bates wrote: > On 05/23/2011 09:31 AM, Tony Hosking wrote: >> An empty subrange gives a warning in the compiler. > > By my experiments, empty subrange, empty enumeration, and arrays > thereof don't warn. Sorry yes, you're right. But usage to declare any variable does. > >> But, the semantics is that it is empty, and has no values of the type. >> You cannot allocate (NEW) an empty type. >> You cannot declare a field of empty type. > > It seems odd that we have this rule for fields, but no corresponding > prohibition against arrays with empty element types. By experiments, > cm3 allows this, for both fixed and open arrays, but treats such array > types as empty types, something the language also does not say. > > At the least, the language and the compiler should agree with each other. > Maybe records/objects and arrays should be treated consistently here? Yes, I suppose so. >> Nor can you declare a variable of empty type. > > Again, oddly, there is no such prohibition in the language against > declaring a formal parameter of empty type. Cm3 prohibits it, > and calls it a 'variable' in the error message. You're right, though it's not the parameter that errors but the variable associated with the parameter. > Again, language and compiler should agree. Can you point me to the relevant entries in the language spec? > > The language also prohibits applying FIRST and LAST to the empty > enumeration, but they are OK applied to an empty subrange. > This makes sense, because they return values of the base type > of the argument type, and such values exist for an empty subrange > but not the empty enumeration, whose base type is only itself. > >> >> On May 23, 2011, at 8:41 AM, Hendrik Boom wrote: >> >>> On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: >>>> >>>> Well, I can build the whole tree and see how many times it helps. >>>> I think this is a pretty standard optimization technique. >>>> Though it'd work better with compiler-derived additional information. >>>> >>>> I initially happened upon this idea developing test cases. >>>> >>>>> The code assumes the minimum of a type is less than or equal to its maximum. >>>> >>>> I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. >>> >>> What *is* the semantics of a range whose minimum is greater than its >>> maximum? There plainly can't be any values in this range. How is a >>> variable of this tyoe initialized? Not to some arbitrary value of the >>> type, because there aren't any. I can see this type being useful to >>> admit convenient generalizations -- for example, an array with n >>> elements can still exist if n happens to be zero, but it seems to me >>> that any code involving a value of the range for subscripts for this >>> array must be simple unexecutable. >>> >>> Or is there some latitude available in the principle that a value of a >>> variable must always be of the correct type? >>> >>> -- hendrik >> >> From rodney_bates at lcwb.coop Mon May 23 20:26:52 2011 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Mon, 23 May 2011 13:26:52 -0500 Subject: [M3devel] range analysis? In-Reply-To: <8C9E1E77-686F-42E0-87FA-B573A4A02CC9@cs.purdue.edu> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> <4DDA8F1A.3070207@lcwb.coop> <8C9E1E77-686F-42E0-87FA-B573A4A02CC9@cs.purdue.edu> Message-ID: <4DDAA6EC.8060401@lcwb.coop> This needs more thought. On the one hand, 2.2.3 on array types allows the explicit element type in either kind of array type definition to be empty, unlike the way 2.2.4 on record types requires a field type to be nonempty. On the other hand, 2.2 has a general prohibition against declaring a variable of empty type, and it is all over the language spec that the elements of arrays are "variables". The general definition of variable in 2.1 would apply to array elements. Thre are numerous places that describe things that can be done with a variable that we all informally know can be done to an element, as it should be and we all have done many times. Moreover, 2.2.3 says in the first paragraph that the elements are variables. So here, the compiler is too liberal, and the language would be clearer with an explicit rule against empty element types. I haven't spotted anywhere a parameter is specifically called a variable, and it is not required to have a nonempty type in the description of parameter declarations. However, it certainly seems to me to fit the definition of variable, and as above, there are lots of things we know can be done with it that the language simply describes as doable to a variable. Moreover, for every mode, there is a rule that at call time, the formal is "bound to" a variable, which pretty well makes it variable in any context where it can be used. Even in a keyword binding, we are getting ready to bind it to a variable very soon. So maybe we need to 1) say a formal parameter is a variable, and 2) say the type in a parameter declaration must be nonempty. The language definition is also full of an ambiguity in its use of "variable" that I have been bothered by in talking about programming languages in general for years. One meaning is the meaning I have been talking about, The other is the kind of variable that is declared by a VAR declaration (not a VAR parameter). There are some uses in the language that I think need to have this latter meaning in order to be right. So we need a different or qualified term for this narrower meaning. On 05/23/2011 11:54 AM, Tony Hosking wrote: > > On May 23, 2011, at 12:45 PM, Rodney M. Bates wrote: > >> On 05/23/2011 09:31 AM, Tony Hosking wrote: >>> An empty subrange gives a warning in the compiler. >> >> By my experiments, empty subrange, empty enumeration, and arrays >> thereof don't warn. > > Sorry yes, you're right. But usage to declare any variable does. > >> >>> But, the semantics is that it is empty, and has no values of the type. >>> You cannot allocate (NEW) an empty type. >>> You cannot declare a field of empty type. >> >> It seems odd that we have this rule for fields, but no corresponding >> prohibition against arrays with empty element types. By experiments, >> cm3 allows this, for both fixed and open arrays, but treats such array >> types as empty types, something the language also does not say. >> >> At the least, the language and the compiler should agree with each other. >> Maybe records/objects and arrays should be treated consistently here? > > Yes, I suppose so. > >>> Nor can you declare a variable of empty type. >> >> Again, oddly, there is no such prohibition in the language against >> declaring a formal parameter of empty type. Cm3 prohibits it, >> and calls it a 'variable' in the error message. > > You're right, though it's not the parameter that errors but the variable associated with the parameter. > >> Again, language and compiler should agree. > > Can you point me to the relevant entries in the language spec? > >> >> The language also prohibits applying FIRST and LAST to the empty >> enumeration, but they are OK applied to an empty subrange. >> This makes sense, because they return values of the base type >> of the argument type, and such values exist for an empty subrange >> but not the empty enumeration, whose base type is only itself. >> >>> >>> On May 23, 2011, at 8:41 AM, Hendrik Boom wrote: >>> >>>> On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: >>>>> >>>>> Well, I can build the whole tree and see how many times it helps. >>>>> I think this is a pretty standard optimization technique. >>>>> Though it'd work better with compiler-derived additional information. >>>>> >>>>> I initially happened upon this idea developing test cases. >>>>> >>>>>> The code assumes the minimum of a type is less than or equal to its maximum. >>>>> >>>>> I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. >>>> >>>> What *is* the semantics of a range whose minimum is greater than its >>>> maximum? There plainly can't be any values in this range. How is a >>>> variable of this tyoe initialized? Not to some arbitrary value of the >>>> type, because there aren't any. I can see this type being useful to >>>> admit convenient generalizations -- for example, an array with n >>>> elements can still exist if n happens to be zero, but it seems to me >>>> that any code involving a value of the range for subscripts for this >>>> array must be simple unexecutable. >>>> >>>> Or is there some latitude available in the principle that a value of a >>>> variable must always be of the correct type? >>>> >>>> -- hendrik >>> >>> > > From hosking at cs.purdue.edu Mon May 23 20:45:37 2011 From: hosking at cs.purdue.edu (Tony Hosking) Date: Mon, 23 May 2011 14:45:37 -0400 Subject: [M3devel] range analysis? In-Reply-To: <4DDAA6EC.8060401@lcwb.coop> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> <4DDA8F1A.3070207@lcwb.coop> <8C9E1E77-686F-42E0-87FA-B573A4A02CC9@cs.purdue.edu> <4DDAA6EC.8060401@lcwb.coop> Message-ID: <45B5D160-9E80-4BB9-8411-F3976BCDC207@cs.purdue.edu> On May 23, 2011, at 2:26 PM, Rodney M. Bates wrote: > This needs more thought. On the one hand, 2.2.3 on array types allows > the explicit element type in either kind of array type definition to > be empty, unlike the way 2.2.4 on record types requires a field type > to be nonempty. I note that an array type of empty elements is itself empty and cannot be instantiated. > On the other hand, 2.2 has a general prohibition against declaring a > variable of empty type, and it is all over the language spec that the > elements of arrays are "variables". The general definition of variable > in 2.1 would apply to array elements. Thre are numerous places that > describe things that can be done with a variable that we all informally > know can be done to an element, as it should be and we all have done > many times. Moreover, 2.2.3 says in the first paragraph that the > elements are variables. So, it seems to me that we could simply disallow empty array elements and be within spec. > So here, the compiler is too liberal, and the language would be clearer > with an explicit rule against empty element types. Right. > I haven't spotted anywhere a parameter is specifically called a variable, > and it is not required to have a nonempty type in the description of > parameter declarations. However, it certainly seems to me to fit > the definition of variable, and as above, there are lots of things > we know can be done with it that the language simply describes as > doable to a variable. Moreover, for every mode, there is a rule > that at call time, the formal is "bound to" a variable, which pretty > well makes it variable in any context where it can be used. Even in > a keyword binding, we are getting ready to bind it to a variable > very soon. Right. > So maybe we need to 1) say a formal parameter is a variable, and A formal parameter is not in itself a variable. It's part of a type (the signature) not an implementation of that type. But every formal parameter has a corresponding variable in the body of the procedure that implements a given signature. > 2) say the type in a parameter declaration must be nonempty. This seems overwrought. I would stop simply at the variables (not the types) and let the binding of formal parameters to variables take care of the check as it currently does. > The language definition is also full of an ambiguity in its use > of "variable" that I have been bothered by in talking about programming > languages in general for years. One meaning is the meaning I have been > talking about, The other is the kind of variable that is declared by a > VAR declaration (not a VAR parameter). There are some uses in the > language that I think need to have this latter meaning in order to be right. Can you enumerate? > So we need a different or qualified term for this narrower meaning. > > On 05/23/2011 11:54 AM, Tony Hosking wrote: >> >> On May 23, 2011, at 12:45 PM, Rodney M. Bates wrote: >> >>> On 05/23/2011 09:31 AM, Tony Hosking wrote: >>>> An empty subrange gives a warning in the compiler. >>> >>> By my experiments, empty subrange, empty enumeration, and arrays >>> thereof don't warn. >> >> Sorry yes, you're right. But usage to declare any variable does. >> >>> >>>> But, the semantics is that it is empty, and has no values of the type. >>>> You cannot allocate (NEW) an empty type. >>>> You cannot declare a field of empty type. >>> >>> It seems odd that we have this rule for fields, but no corresponding >>> prohibition against arrays with empty element types. By experiments, >>> cm3 allows this, for both fixed and open arrays, but treats such array >>> types as empty types, something the language also does not say. >>> >>> At the least, the language and the compiler should agree with each other. >>> Maybe records/objects and arrays should be treated consistently here? >> >> Yes, I suppose so. >> >>>> Nor can you declare a variable of empty type. >>> >>> Again, oddly, there is no such prohibition in the language against >>> declaring a formal parameter of empty type. Cm3 prohibits it, >>> and calls it a 'variable' in the error message. >> >> You're right, though it's not the parameter that errors but the variable associated with the parameter. >> >>> Again, language and compiler should agree. >> >> Can you point me to the relevant entries in the language spec? >> >>> >>> The language also prohibits applying FIRST and LAST to the empty >>> enumeration, but they are OK applied to an empty subrange. >>> This makes sense, because they return values of the base type >>> of the argument type, and such values exist for an empty subrange >>> but not the empty enumeration, whose base type is only itself. >>> >>>> >>>> On May 23, 2011, at 8:41 AM, Hendrik Boom wrote: >>>> >>>>> On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: >>>>>> >>>>>> Well, I can build the whole tree and see how many times it helps. >>>>>> I think this is a pretty standard optimization technique. >>>>>> Though it'd work better with compiler-derived additional information. >>>>>> >>>>>> I initially happened upon this idea developing test cases. >>>>>> >>>>>>> The code assumes the minimum of a type is less than or equal to its maximum. >>>>>> >>>>>> I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. >>>>> >>>>> What *is* the semantics of a range whose minimum is greater than its >>>>> maximum? There plainly can't be any values in this range. How is a >>>>> variable of this tyoe initialized? Not to some arbitrary value of the >>>>> type, because there aren't any. I can see this type being useful to >>>>> admit convenient generalizations -- for example, an array with n >>>>> elements can still exist if n happens to be zero, but it seems to me >>>>> that any code involving a value of the range for subscripts for this >>>>> array must be simple unexecutable. >>>>> >>>>> Or is there some latitude available in the principle that a value of a >>>>> variable must always be of the correct type? >>>>> >>>>> -- hendrik >>>> >>>> >> >> From dabenavidesd at yahoo.es Mon May 23 22:44:11 2011 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Mon, 23 May 2011 21:44:11 +0100 (BST) Subject: [M3devel] range analysis? In-Reply-To: Message-ID: <346693.80219.qm@web29707.mail.ird.yahoo.com> Hi all: in one process it might be good to check for those optimization, but then you might want to abstract them all to allow to be pessimistic or to analyze them in ESC. This should require some good knowledge of the compiler though, which is maybe a harder task than just build a VCG but perhaps is too slow for m3cg, maybe for native backends, is more justifiable if so. Perhaps there is enough good trade off to do so. Thanks in advance --- El dom, 22/5/11, Jay K escribi?: De: Jay K Asunto: Re: [M3devel] range analysis? Para: "Tony" CC: "m3devel" Fecha: domingo, 22 de mayo, 2011 18:18 Well, I can build the whole tree and see how many times it helps. I think this is a pretty standard optimization technique. Though it'd work better with compiler-derived additional information. I initially happened upon this idea developing test cases. ?> The code assumes the minimum of a type is less than or equal to its maximum. I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. ?- Jay Subject: Re: range analysis? From: hosking at cs.purdue.edu Date: Sun, 22 May 2011 14:51:59 -0400 CC: m3devel at elegosoft.com To: jay.krell at cornell.edu So, one question is: what benefit does this really give? ?Your examples seem a little contrived. On May 22, 2011, at 4:26 AM, Jay K wrote: I've been sitting on this diff a long while. In some places the frontend knows the bounds of a type/value and will optimize away range checks. I'm pretty sure. This makes it do that more. I haven't looked at or tested this in ages. But the basic idea seems sound, simple, easy enough to get a few small wins from. For example if you have: a: [-10..-1]; b: [1..10]; then all comparisons between a and b are compile-time constant. Comparisons of cardinals to negative numbers, likewise. One thing maybe missing below is handling of empty ranges like a: [1..-1]; The code assumes the minimum of a type is less than or equal to its maximum. Index: m3-sys/m3front/src/misc/CG.i3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.i3,v retrieving revision 1.15 diff -r1.15 CG.i3 11c11 < IMPORT Target, M3CG, M3; --- > IMPORT Target, M3CG, M3, TInt; 402c402,406 < PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type); --- > PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type; >???????????????? min_valid: BOOLEAN := FALSE; >???????????????? max_valid: BOOLEAN := FALSE; >???????????????? min: Target.Int := TInt.Zero; >???????????????? max: Target.Int := TInt.Zero); 414,415c418,423 < PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0); < (* == Load (v, o, t.size, t.align, t) *) --- > PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0; >???????????????????? min_valid: BOOLEAN := FALSE; >???????????????????? max_valid: BOOLEAN := FALSE; >???????????????????? min: Target.Int := TInt.Zero; >???????????????????? max: Target.Int := TInt.Zero); > (* == Load (v, o, t.size, t.align, t, min/max...) *) Index: m3-sys/m3front/src/misc/CG.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.m3,v retrieving revision 1.40 diff -r1.40 CG.m3 13c13 < IMPORT M3, M3CG, M3CG_Ops, M3CG_Check; --- > IMPORT M3, M3CG, M3CG_Ops, M3CG_Check, RTIO, RTParams; 45a46,49 >???? min_valid : BOOLEAN := FALSE; (* whether or not min is valid *) >???? max_valid : BOOLEAN := FALSE; (* whether or not max is valid *) >???? min?????? : Target.Int := TInt.Zero; (* the minimum possible value *) >???? max?????? : Target.Int := TInt.Zero; (* the maximum possible value *) 80c84,85 < VAR --- > VAR >?? debug := FALSE; 604a610,614 >???? v.min?????? := TInt.Zero; >???? v.max?????? := TInt.Zero; >???? v.min_valid := FALSE; >???? v.max_valid := FALSE; >? 766a777,780 >???? x.min?????? := TInt.Zero; >???? x.max?????? := TInt.Zero; >???? x.min_valid := FALSE; >???? x.max_valid := FALSE; 978a993,995 >?????? IF debug THEN >???????? RTIO.PutText("m3front:cg:Init_int:NOT in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); >?????? END; 980a998,1001 >???? END; >? >???? IF debug THEN >?????? RTIO.PutText("m3front:cg:Init_int:in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); 1266c1287,1291 < PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type) = --- > PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type; >???????????????? min_valid: BOOLEAN := FALSE; >???????????????? max_valid: BOOLEAN := FALSE; >???????????????? min: Target.Int := TInt.Zero; >???????????????? max: Target.Int := TInt.Zero) = 1276c1301 ?????? SimpleLoad (v, o, t, min_valid, max_valid, min, max); 1291c1316 ???????? SimpleLoad (v, o, best_type, min_valid, max_valid, min, max); 1312c1337,1341 < PROCEDURE SimpleLoad (v: Var;? o: Offset;? t: Type) = --- > PROCEDURE SimpleLoad (v: Var;? o: Offset;? t: Type; >?????????????????????? min_valid: BOOLEAN := FALSE; >?????????????????????? max_valid: BOOLEAN := FALSE; >?????????????????????? min: Target.Int := TInt.Zero; >?????????????????????? max: Target.Int := TInt.Zero) = 1323a1353,1356 >?????? x.min_valid := min_valid; >?????? x.max_valid := max_valid; >?????? x.min?????? := min; >?????? x.max?????? := max; 1339a1373,1376 >?????? x.min?????? := TInt.Zero; >?????? x.max?????? := TInt.Zero; >?????? x.min_valid := FALSE; >?????? x.max_valid := FALSE; 1347a1385,1388 >???? stack[tos-1].min?????? := TInt.Zero; >???? stack[tos-1].max?????? := TInt.Zero; >???? stack[tos-1].min_valid := FALSE; >???? stack[tos-1].max_valid := FALSE; 1350c1391,1395 < PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0) = --- > PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0; >???????????????????? min_valid: BOOLEAN := FALSE; >???????????????????? max_valid: BOOLEAN := FALSE; >???????????????????? min: Target.Int := TInt.Zero; >???????????????????? max: Target.Int := TInt.Zero) = 1352c1397 ???? SimpleLoad (v, o, t, min_valid, max_valid, min, max); 1815a1861,1864 >?????? x.min_valid := TRUE; >?????? x.max_valid := TRUE; >?????? x.min := i; >?????? x.max := i; 1832,1834c1881,2007 ?? VAR always_true: BOOLEAN; >?????? always_false: BOOLEAN; >?????? left_type: Type; >?????? right_type: Type; >?????? left_min: Target.Int; >?????? left_max: Target.Int; >?????? right_min: Target.Int; >?????? right_max: Target.Int; >?????? left_signed: BOOLEAN; >?????? right_signed: BOOLEAN; >?? BEGIN >? >???? always_true := FALSE; >???? always_false := FALSE; >? >???? WITH left? = stack [SCheck (2, "Compare-left")], >????????? right = stack [SCheck (1, "Compare-right")] DO >? >?????? left_type := left.type; >?????? right_type := right.type; >? >?????? IF????? left.min_valid >?????????? AND left.max_valid >?????????? AND right.min_valid >?????????? AND right.max_valid >?????????? AND Target.OrdinalType[left_type] >?????????? AND Target.OrdinalType[right_type] THEN >? >???????? left_min := left.min; >???????? left_max := left.max; >???????? right_min := right.min; >???????? right_max := right.max; >???????? left_signed := Target.SignedType[left_type]; >???????? right_signed := Target.SignedType[right_type]; >? >???????? (* First handle types that match in signedness. *) >? >???????? IF left_signed = right_signed THEN >? >?????????? (* Check for ranges with no overlap. *) >? >?????????? IF left_signed (* and right_signed *) THEN >???????????? IF TInt.LT(left_max, right_min) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; >???????????? ELSIF TInt.GT(left_min, right_max) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; >???????????? END; >?????????? ELSE (* left_signed and right_signed both false *) >???????????? IF TWord.LT(left_max, right_min) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; >???????????? ELSIF TWord.GT(left_min, right_max) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; >???????????? END; >?????????? END; >? >?????????? (* Check for overlap just on the edge, e.g. [0..1] compared to [1..2]. *) >? >?????????? IF NOT (always_true OR always_false) THEN >???????????? IF TInt.EQ(left_max, right_min) THEN >?????????????? always_true := op = Cmp.LE; >?????????????? always_false := op = Cmp.GT; >???????????? ELSIF TInt.EQ(left_min, right_max) THEN >?????????????? always_true := op = Cmp.GE; >?????????????? always_false := op = Cmp.LT; >???????????? END; >?????????? END; >? >?????????? (* Handle equal subranges with one element, not likely to occur. *) >? >?????????? IF NOT (always_true OR always_false) THEN >???????????? IF????? TInt.EQ(left_max, left_min) >???????????????? AND TInt.EQ(left_max, right_max) >???????????????? AND TInt.EQ(left_max, right_min) THEN >?????????????? always_true? := op IN SET OF Cmp{Cmp.GE, Cmp.LE, Cmp.EQ}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.GT, Cmp.NE}; >???????????? END; >?????????? END; >???????? ELSE >? >?????????? (* Now deal with mixed up types (signed compared to unsigned). >??????????? * We may be able to merge these by setting some min/max >??????????? * to zero. That is, the minimum of an unsigned type is zero. >??????????? * However we want to be sure not to interpret unsigned min/max >??????????? * as signed. >??????????? *) >? >?????????? IF left_signed THEN >???????????? IF TInt.LT(left_max, TInt.Zero) THEN >?????????????? always_true? := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; >???????????? ELSIF TInt.EQ(left_max, TInt.Zero) THEN >?????????????? always_true? := op = Cmp.LE; >?????????????? always_false := op = Cmp.GT; >???????????? END; >?????????? ELSE (* right is signed *) >???????????? IF TInt.LT(right_max, TInt.Zero) THEN >?????????????? always_true? := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; >???????????? ELSIF TInt.EQ(right_max, TInt.Zero) THEN >?????????????? always_true := op = Cmp.GE; >?????????????? always_false := op = Cmp.LT; >???????????? END; >?????????? END; >???????? END; >?????? END; >?? >?????? <* ASSERT NOT (always_true AND always_false) *> >? >?????? IF always_true OR always_false THEN >???????? Discard(right_type); >???????? Discard(left_type); >???????? IF always_true THEN >?????????? cg.load_integer (Target.Integer.cg_type, TInt.One); >???????? ELSE >?????????? cg.load_integer (Target.Integer.cg_type, TInt.Zero); >???????? END >?????? ELSE >???????? IF Force_pair (commute := TRUE) THEN >?????????? op := M3CG.SwappedCompare [op]; >???????? END; >???????? cg.compare (t, Target.Integer.cg_type, op); >???????? SPop (2, "Compare"); >?????? END; 1836,1837d2008 ?????? x.min?????? := TInt.Zero; >?????? x.max?????? := TInt.Zero; >?????? x.min_valid := FALSE; >?????? x.max_valid := FALSE; 2977c3152,3153 < BEGIN --- > BEGIN >?? debug := debug OR RTParams.IsPresent ("m3front_cg_debug"); Index: m3-sys/m3front/src/values/Variable.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/values/Variable.m3,v retrieving revision 1.13 diff -r1.13 Variable.m3 362a363,365 >?? VAR min: Target.Int; >?????? max: Target.Int; >?????? bounds_valid: BOOLEAN; 395c398,401 ???????? (*GetBounds (t, min, max); >???????? bounds_valid := TInt.LE(min, max);*) >???????? bounds_valid := t.tipe # NIL AND Type.GetBounds(t.tipe, min, max) AND TInt.LE(min, max); >???????? CG.Load (t.cg_var, t.offset, t.size, t.cg_align, t.stk_type, bounds_valid, bounds_valid, min, max); -------------- next part -------------- An HTML attachment was scrubbed... URL: From hendrik at topoi.pooq.com Tue May 24 00:53:02 2011 From: hendrik at topoi.pooq.com (Hendrik Boom) Date: Mon, 23 May 2011 18:53:02 -0400 Subject: [M3devel] range analysis? In-Reply-To: <4DDAA6EC.8060401@lcwb.coop> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> <4DDA8F1A.3070207@lcwb.coop> <8C9E1E77-686F-42E0-87FA-B573A4A02CC9@cs.purdue.edu> <4DDAA6EC.8060401@lcwb.coop> Message-ID: <20110523225302.GA8980@topoi.pooq.com> On Mon, May 23, 2011 at 01:26:52PM -0500, Rodney M. Bates wrote: > This needs more thought. On the one hand, 2.2.3 on array types allows > the explicit element type in either kind of array type definition to > be empty, Well, the array might be empty, in which case no nonexistent values would be required when the array is created. > unlike the way 2.2.4 on record types requires a field type > to be nonempty. > > On the other hand, 2.2 has a general prohibition against declaring a > variable of empty type, and it is all over the language spec that the > elements of arrays are "variables". The general definition of variable > in 2.1 would apply to array elements. Thre are numerous places that > describe things that can be done with a variable that we all informally > know can be done to an element, as it should be and we all have done > many times. Moreover, 2.2.3 says in the first paragraph that the > elements are variables. > > So here, the compiler is too liberal, and the language would be clearer > with an explicit rule against empty element types. > > I haven't spotted anywhere a parameter is specifically called a variable, > and it is not required to have a nonempty type in the description of > parameter declarations. However, it certainly seems to me to fit > the definition of variable, and as above, there are lots of things > we know can be done with it that the language simply describes as > doable to a variable. Moreover, for every mode, there is a rule > that at call time, the formal is "bound to" a variable, which pretty > well makes it variable in any context where it can be used. Even in > a keyword binding, we are getting ready to bind it to a variable > very soon. > > So maybe we need to 1) say a formal parameter is a variable, and > 2) say the type in a parameter declaration must be nonempty. > > The language definition is also full of an ambiguity in its use > of "variable" that I have been bothered by in talking about programming > languages in general for years. One meaning is the meaning I have been > talking about, The other is the kind of variable that is declared by a > VAR declaration (not a VAR parameter). There are some uses in the > language that I think need to have this latter meaning in order to be right. > > So we need a different or qualified term for this narrower meaning. > > On 05/23/2011 11:54 AM, Tony Hosking wrote: >> >> On May 23, 2011, at 12:45 PM, Rodney M. Bates wrote: >> >>> On 05/23/2011 09:31 AM, Tony Hosking wrote: >>>> An empty subrange gives a warning in the compiler. >>> >>> By my experiments, empty subrange, empty enumeration, and arrays >>> thereof don't warn. >> >> Sorry yes, you're right. But usage to declare any variable does. >> >>> >>>> But, the semantics is that it is empty, and has no values of the type. >>>> You cannot allocate (NEW) an empty type. >>>> You cannot declare a field of empty type. >>> >>> It seems odd that we have this rule for fields, but no corresponding >>> prohibition against arrays with empty element types. By experiments, >>> cm3 allows this, for both fixed and open arrays, but treats such array >>> types as empty types, something the language also does not say. >>> >>> At the least, the language and the compiler should agree with each other. >>> Maybe records/objects and arrays should be treated consistently here? >> >> Yes, I suppose so. >> >>>> Nor can you declare a variable of empty type. >>> >>> Again, oddly, there is no such prohibition in the language against >>> declaring a formal parameter of empty type. Cm3 prohibits it, >>> and calls it a 'variable' in the error message. >> >> You're right, though it's not the parameter that errors but the variable associated with the parameter. >> >>> Again, language and compiler should agree. >> >> Can you point me to the relevant entries in the language spec? >> >>> >>> The language also prohibits applying FIRST and LAST to the empty >>> enumeration, but they are OK applied to an empty subrange. >>> This makes sense, because they return values of the base type >>> of the argument type, and such values exist for an empty subrange >>> but not the empty enumeration, whose base type is only itself. >>> >>>> >>>> On May 23, 2011, at 8:41 AM, Hendrik Boom wrote: >>>> >>>>> On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: >>>>>> >>>>>> Well, I can build the whole tree and see how many times it helps. >>>>>> I think this is a pretty standard optimization technique. >>>>>> Though it'd work better with compiler-derived additional information. >>>>>> >>>>>> I initially happened upon this idea developing test cases. >>>>>> >>>>>>> The code assumes the minimum of a type is less than or equal to its maximum. >>>>>> >>>>>> I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. >>>>> >>>>> What *is* the semantics of a range whose minimum is greater than its >>>>> maximum? There plainly can't be any values in this range. How is a >>>>> variable of this tyoe initialized? Not to some arbitrary value of the >>>>> type, because there aren't any. I can see this type being useful to >>>>> admit convenient generalizations -- for example, an array with n >>>>> elements can still exist if n happens to be zero, but it seems to me >>>>> that any code involving a value of the range for subscripts for this >>>>> array must be simple unexecutable. >>>>> >>>>> Or is there some latitude available in the principle that a value of a >>>>> variable must always be of the correct type? >>>>> >>>>> -- hendrik >>>> >>>> >> >> From hendrik at topoi.pooq.com Tue May 24 00:55:08 2011 From: hendrik at topoi.pooq.com (Hendrik Boom) Date: Mon, 23 May 2011 18:55:08 -0400 Subject: [M3devel] range analysis? In-Reply-To: <45B5D160-9E80-4BB9-8411-F3976BCDC207@cs.purdue.edu> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> <4DDA8F1A.3070207@lcwb.coop> <8C9E1E77-686F-42E0-87FA-B573A4A02CC9@cs.purdue.edu> <4DDAA6EC.8060401@lcwb.coop> <45B5D160-9E80-4BB9-8411-F3976BCDC207@cs.purdue.edu> Message-ID: <20110523225508.GB8980@topoi.pooq.com> On Mon, May 23, 2011 at 02:45:37PM -0400, Tony Hosking wrote: > > On May 23, 2011, at 2:26 PM, Rodney M. Bates wrote: > > > This needs more thought. On the one hand, 2.2.3 on array types allows > > the explicit element type in either kind of array type definition to > > be empty, unlike the way 2.2.4 on record types requires a field type > > to be nonempty. > > I note that an array type of empty elements is itself empty and cannot be instantiated. > > > On the other hand, 2.2 has a general prohibition against declaring a > > variable of empty type, and it is all over the language spec that the > > elements of arrays are "variables". The general definition of variable > > in 2.1 would apply to array elements. Thre are numerous places that > > describe things that can be done with a variable that we all informally > > know can be done to an element, as it should be and we all have done > > many times. Moreover, 2.2.3 says in the first paragraph that the > > elements are variables. > > So, it seems to me that we could simply disallow empty array elements and be within spec. You mean the array elements are empty? or that the element type is empty? These are very different concepts. From dabenavidesd at yahoo.es Tue May 24 00:54:33 2011 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Mon, 23 May 2011 23:54:33 +0100 (BST) Subject: [M3devel] range analysis? In-Reply-To: <346693.80219.qm@web29707.mail.ird.yahoo.com> Message-ID: <781156.80626.qm@web29716.mail.ird.yahoo.com> Hi all: an this could be even more payable in embedded architectures, of course there is always more work, but the market, is moving towards that I mean, people are *really* worried about lock-free data structures, etc, when there are tools that tackle that automatically or treat them formally and in Modula-3, see: http://www.eetimes.com/discussion/break-points/4027598/Executing-software-contracts I'm thinking in this more seriously, and by the amount of time they devised modula-3 end (1996 if I may say so), which is at least 10 years ahead of its common use and the tools they did as was their goal in DEC SRC, we are still on the front or struggling if so (and off-time of 5 years still have some room to speak up). And could be more if you think in separate efforts on it. As I heard from an old M3 friend, Obliq was? merely about to be the language standard for web and yet not one of them has the full technology of it as is (meaning it was the first agent language and it has type inference, and it's fast!). think in the Java JS binomial, for example and alike. I mean such an example, of usage and precedence in time is enough to say the quality in terms of the all package (Modula-3 and scripting language) Ok, it would be interesting to see why did they to take such decision (old friend's wish). Thanks in advance --- El lun, 23/5/11, Daniel Alejandro Benavides D. escribi?: De: Daniel Alejandro Benavides D. Asunto: Re: [M3devel] range analysis? Para: "Tony" , "Jay K" CC: "m3devel" Fecha: lunes, 23 de mayo, 2011 15:44 Hi all: in one process it might be good to check for those optimization, but then you might want to abstract them all to allow to be pessimistic or to analyze them in ESC. This should require some good knowledge of the compiler though, which is maybe a harder task than just build a VCG but perhaps is too slow for m3cg, maybe for native backends, is more justifiable if so. Perhaps there is enough good trade off to do so. Thanks in advance --- El dom, 22/5/11, Jay K escribi?: De: Jay K Asunto: Re: [M3devel] range analysis? Para: "Tony" CC: "m3devel" Fecha: domingo, 22 de mayo, 2011 18:18 Well, I can build the whole tree and see how many times it helps. I think this is a pretty standard optimization technique. Though it'd work better with compiler-derived additional information. I initially happened upon this idea developing test cases. ?> The code assumes the minimum of a type is less than or equal to its maximum. I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. ?- Jay Subject: Re: range analysis? From: hosking at cs.purdue.edu Date: Sun, 22 May 2011 14:51:59 -0400 CC: m3devel at elegosoft.com To: jay.krell at cornell.edu So, one question is: what benefit does this really give? ?Your examples seem a little contrived. On May 22, 2011, at 4:26 AM, Jay K wrote: I've been sitting on this diff a long while. In some places the frontend knows the bounds of a type/value and will optimize away range checks. I'm pretty sure. This makes it do that more. I haven't looked at or tested this in ages. But the basic idea seems sound, simple, easy enough to get a few small wins from. For example if you have: a: [-10..-1]; b: [1..10]; then all comparisons between a and b are compile-time constant. Comparisons of cardinals to negative numbers, likewise. One thing maybe missing below is handling of empty ranges like a: [1..-1]; The code assumes the minimum of a type is less than or equal to its maximum. Index: m3-sys/m3front/src/misc/CG.i3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.i3,v retrieving revision 1.15 diff -r1.15 CG.i3 11c11 < IMPORT Target, M3CG, M3; --- > IMPORT Target, M3CG, M3, TInt; 402c402,406 < PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type); --- > PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type; >???????????????? min_valid: BOOLEAN := FALSE; >???????????????? max_valid: BOOLEAN := FALSE; >???????????????? min: Target.Int := TInt.Zero; >???????????????? max: Target.Int := TInt.Zero); 414,415c418,423 < PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0); < (* == Load (v, o, t.size, t.align, t) *) --- > PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0; >???????????????????? min_valid: BOOLEAN := FALSE; >???????????????????? max_valid: BOOLEAN := FALSE; >???????????????????? min: Target.Int := TInt.Zero; >???????????????????? max: Target.Int := TInt.Zero); > (* == Load (v, o, t.size, t.align, t, min/max...) *) Index: m3-sys/m3front/src/misc/CG.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.m3,v retrieving revision 1.40 diff -r1.40 CG.m3 13c13 < IMPORT M3, M3CG, M3CG_Ops, M3CG_Check; --- > IMPORT M3, M3CG, M3CG_Ops, M3CG_Check, RTIO, RTParams; 45a46,49 >???? min_valid : BOOLEAN := FALSE; (* whether or not min is valid *) >???? max_valid : BOOLEAN := FALSE; (* whether or not max is valid *) >???? min?????? : Target.Int := TInt.Zero; (* the minimum possible value *) >???? max?????? : Target.Int := TInt.Zero; (* the maximum possible value *) 80c84,85 < VAR --- > VAR >?? debug := FALSE; 604a610,614 >???? v.min?????? := TInt.Zero; >???? v.max?????? := TInt.Zero; >???? v.min_valid := FALSE; >???? v.max_valid := FALSE; >? 766a777,780 >???? x.min?????? := TInt.Zero; >???? x.max?????? := TInt.Zero; >???? x.min_valid := FALSE; >???? x.max_valid := FALSE; 978a993,995 >?????? IF debug THEN >???????? RTIO.PutText("m3front:cg:Init_int:NOT in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); >?????? END; 980a998,1001 >???? END; >? >???? IF debug THEN >?????? RTIO.PutText("m3front:cg:Init_int:in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); 1266c1287,1291 < PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type) = --- > PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type; >???????????????? min_valid: BOOLEAN := FALSE; >???????????????? max_valid: BOOLEAN := FALSE; >???????????????? min: Target.Int := TInt.Zero; >???????????????? max: Target.Int := TInt.Zero) = 1276c1301 ?????? SimpleLoad (v, o, t, min_valid, max_valid, min, max); 1291c1316 ???????? SimpleLoad (v, o, best_type, min_valid, max_valid, min, max); 1312c1337,1341 < PROCEDURE SimpleLoad (v: Var;? o: Offset;? t: Type) = --- > PROCEDURE SimpleLoad (v: Var;? o: Offset;? t: Type; >?????????????????????? min_valid: BOOLEAN := FALSE; >?????????????????????? max_valid: BOOLEAN := FALSE; >?????????????????????? min: Target.Int := TInt.Zero; >?????????????????????? max: Target.Int := TInt.Zero) = 1323a1353,1356 >?????? x.min_valid := min_valid; >?????? x.max_valid := max_valid; >?????? x.min?????? := min; >?????? x.max?????? := max; 1339a1373,1376 >?????? x.min?????? := TInt.Zero; >?????? x.max?????? := TInt.Zero; >?????? x.min_valid := FALSE; >?????? x.max_valid := FALSE; 1347a1385,1388 >???? stack[tos-1].min?????? := TInt.Zero; >???? stack[tos-1].max?????? := TInt.Zero; >???? stack[tos-1].min_valid := FALSE; >???? stack[tos-1].max_valid := FALSE; 1350c1391,1395 < PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0) = --- > PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0; >???????????????????? min_valid: BOOLEAN := FALSE; >???????????????????? max_valid: BOOLEAN := FALSE; >???????????????????? min: Target.Int := TInt.Zero; >???????????????????? max: Target.Int := TInt.Zero) = 1352c1397 ???? SimpleLoad (v, o, t, min_valid, max_valid, min, max); 1815a1861,1864 >?????? x.min_valid := TRUE; >?????? x.max_valid := TRUE; >?????? x.min := i; >?????? x.max := i; 1832,1834c1881,2007 ?? VAR always_true: BOOLEAN; >?????? always_false: BOOLEAN; >?????? left_type: Type; >?????? right_type: Type; >?????? left_min: Target.Int; >?????? left_max: Target.Int; >?????? right_min: Target.Int; >?????? right_max: Target.Int; >?????? left_signed: BOOLEAN; >?????? right_signed: BOOLEAN; >?? BEGIN >? >???? always_true := FALSE; >???? always_false := FALSE; >? >???? WITH left? = stack [SCheck (2, "Compare-left")], >????????? right = stack [SCheck (1, "Compare-right")] DO >? >?????? left_type := left.type; >?????? right_type := right.type; >? >?????? IF????? left.min_valid >?????????? AND left.max_valid >?????????? AND right.min_valid >?????????? AND right.max_valid >?????????? AND Target.OrdinalType[left_type] >?????????? AND Target.OrdinalType[right_type] THEN >? >???????? left_min := left.min; >???????? left_max := left.max; >???????? right_min := right.min; >???????? right_max := right.max; >???????? left_signed := Target.SignedType[left_type]; >???????? right_signed := Target.SignedType[right_type]; >? >???????? (* First handle types that match in signedness. *) >? >???????? IF left_signed = right_signed THEN >? >?????????? (* Check for ranges with no overlap. *) >? >?????????? IF left_signed (* and right_signed *) THEN >???????????? IF TInt.LT(left_max, right_min) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; >???????????? ELSIF TInt.GT(left_min, right_max) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; >???????????? END; >?????????? ELSE (* left_signed and right_signed both false *) >???????????? IF TWord.LT(left_max, right_min) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; >???????????? ELSIF TWord.GT(left_min, right_max) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; >???????????? END; >?????????? END; >? >?????????? (* Check for overlap just on the edge, e.g. [0..1] compared to [1..2]. *) >? >?????????? IF NOT (always_true OR always_false) THEN >???????????? IF TInt.EQ(left_max, right_min) THEN >?????????????? always_true := op = Cmp.LE; >?????????????? always_false := op = Cmp.GT; >???????????? ELSIF TInt.EQ(left_min, right_max) THEN >?????????????? always_true := op = Cmp.GE; >?????????????? always_false := op = Cmp.LT; >???????????? END; >?????????? END; >? >?????????? (* Handle equal subranges with one element, not likely to occur. *) >? >?????????? IF NOT (always_true OR always_false) THEN >???????????? IF????? TInt.EQ(left_max, left_min) >???????????????? AND TInt.EQ(left_max, right_max) >???????????????? AND TInt.EQ(left_max, right_min) THEN >?????????????? always_true? := op IN SET OF Cmp{Cmp.GE, Cmp.LE, Cmp.EQ}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.GT, Cmp.NE}; >???????????? END; >?????????? END; >???????? ELSE >? >?????????? (* Now deal with mixed up types (signed compared to unsigned). >??????????? * We may be able to merge these by setting some min/max >??????????? * to zero. That is, the minimum of an unsigned type is zero. >??????????? * However we want to be sure not to interpret unsigned min/max >??????????? * as signed. >??????????? *) >? >?????????? IF left_signed THEN >???????????? IF TInt.LT(left_max, TInt.Zero) THEN >?????????????? always_true? := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; >???????????? ELSIF TInt.EQ(left_max, TInt.Zero) THEN >?????????????? always_true? := op = Cmp.LE; >?????????????? always_false := op = Cmp.GT; >???????????? END; >?????????? ELSE (* right is signed *) >???????????? IF TInt.LT(right_max, TInt.Zero) THEN >?????????????? always_true? := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; >???????????? ELSIF TInt.EQ(right_max, TInt.Zero) THEN >?????????????? always_true := op = Cmp.GE; >?????????????? always_false := op = Cmp.LT; >???????????? END; >?????????? END; >???????? END; >?????? END; >?? >?????? <* ASSERT NOT (always_true AND always_false) *> >? >?????? IF always_true OR always_false THEN >???????? Discard(right_type); >???????? Discard(left_type); >???????? IF always_true THEN >?????????? cg.load_integer (Target.Integer.cg_type, TInt.One); >???????? ELSE >?????????? cg.load_integer (Target.Integer.cg_type, TInt.Zero); >???????? END >?????? ELSE >???????? IF Force_pair (commute := TRUE) THEN >?????????? op := M3CG.SwappedCompare [op]; >???????? END; >???????? cg.compare (t, Target.Integer.cg_type, op); >???????? SPop (2, "Compare"); >?????? END; 1836,1837d2008 ?????? x.min?????? := TInt.Zero; >?????? x.max?????? := TInt.Zero; >?????? x.min_valid := FALSE; >?????? x.max_valid := FALSE; 2977c3152,3153 < BEGIN --- > BEGIN >?? debug := debug OR RTParams.IsPresent ("m3front_cg_debug"); Index: m3-sys/m3front/src/values/Variable.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/values/Variable.m3,v retrieving revision 1.13 diff -r1.13 Variable.m3 362a363,365 >?? VAR min: Target.Int; >?????? max: Target.Int; >?????? bounds_valid: BOOLEAN; 395c398,401 ???????? (*GetBounds (t, min, max); >???????? bounds_valid := TInt.LE(min, max);*) >???????? bounds_valid := t.tipe # NIL AND Type.GetBounds(t.tipe, min, max) AND TInt.LE(min, max); >???????? CG.Load (t.cg_var, t.offset, t.size, t.cg_align, t.stk_type, bounds_valid, bounds_valid, min, max); -------------- next part -------------- An HTML attachment was scrubbed... URL: From dabenavidesd at yahoo.es Tue May 24 01:22:51 2011 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Tue, 24 May 2011 00:22:51 +0100 (BST) Subject: [M3devel] range analysis? In-Reply-To: <781156.80626.qm@web29716.mail.ird.yahoo.com> Message-ID: <970550.60419.qm@web29711.mail.ird.yahoo.com> Hi all: and even more I can tell you there is plenty of teaching material on Object Oriented software construction in Modula-3 for Meyer's book,? then what about pulishing it and rewriting it in scripts of Obliq, which is harder to learn from 0, I guess Modula-3, but even if we facilitate that, what else is missing here (mentor, zeus3D, Obliq3D examples). See the same mentioned linked page. About Second comment on that page, I guess they talk about Model driven checking, from which there are tools that do that and are open source if they are so much we could adapt them to it. See Spec language. Thanks in advance --- El lun, 23/5/11, Daniel Alejandro Benavides D. escribi?: De: Daniel Alejandro Benavides D. Asunto: Re: [M3devel] range analysis? Para: "Tony" , "Jay K" CC: "m3devel" Fecha: lunes, 23 de mayo, 2011 17:54 Hi all: an this could be even more payable in embedded architectures, of course there is always more work, but the market, is moving towards that I mean, people are *really* worried about lock-free data structures, etc, when there are tools that tackle that automatically or treat them formally and in Modula-3, see: http://www.eetimes.com/discussion/break-points/4027598/Executing-software-contracts I'm thinking in this more seriously, and by the amount of time they devised modula-3 end (1996 if I may say so), which is at least 10 years ahead of its common use and the tools they did as was their goal in DEC SRC, we are still on the front or struggling if so (and off-time of 5 years still have some room to speak up). And could be more if you think in separate efforts on it. As I heard from an old M3 friend, Obliq was? merely about to be the language standard for web and yet not one of them has the full technology of it as is (meaning it was the first agent language and it has type inference, and it's fast!). think in the Java JS binomial, for example and alike. I mean such an example, of usage and precedence in time is enough to say the quality in terms of the all package (Modula-3 and scripting language) Ok, it would be interesting to see why did they to take such decision (old friend's wish). Thanks in advance --- El lun, 23/5/11, Daniel Alejandro Benavides D. escribi?: De: Daniel Alejandro Benavides D. Asunto: Re: [M3devel] range analysis? Para: "Tony" , "Jay K" CC: "m3devel" Fecha: lunes, 23 de mayo, 2011 15:44 Hi all: in one process it might be good to check for those optimization, but then you might want to abstract them all to allow to be pessimistic or to analyze them in ESC. This should require some good knowledge of the compiler though, which is maybe a harder task than just build a VCG but perhaps is too slow for m3cg, maybe for native backends, is more justifiable if so. Perhaps there is enough good trade off to do so. Thanks in advance --- El dom, 22/5/11, Jay K escribi?: De: Jay K Asunto: Re: [M3devel] range analysis? Para: "Tony" CC: "m3devel" Fecha: domingo, 22 de mayo, 2011 18:18 Well, I can build the whole tree and see how many times it helps. I think this is a pretty standard optimization technique. Though it'd work better with compiler-derived additional information. I initially happened upon this idea developing test cases. ?> The code assumes the minimum of a type is less than or equal to its maximum. I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. ?- Jay Subject: Re: range analysis? From: hosking at cs.purdue.edu Date: Sun, 22 May 2011 14:51:59 -0400 CC: m3devel at elegosoft.com To: jay.krell at cornell.edu So, one question is: what benefit does this really give? ?Your examples seem a little contrived. On May 22, 2011, at 4:26 AM, Jay K wrote: I've been sitting on this diff a long while. In some places the frontend knows the bounds of a type/value and will optimize away range checks. I'm pretty sure. This makes it do that more. I haven't looked at or tested this in ages. But the basic idea seems sound, simple, easy enough to get a few small wins from. For example if you have: a: [-10..-1]; b: [1..10]; then all comparisons between a and b are compile-time constant. Comparisons of cardinals to negative numbers, likewise. One thing maybe missing below is handling of empty ranges like a: [1..-1]; The code assumes the minimum of a type is less than or equal to its maximum. Index: m3-sys/m3front/src/misc/CG.i3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.i3,v retrieving revision 1.15 diff -r1.15 CG.i3 11c11 < IMPORT Target, M3CG, M3; --- > IMPORT Target, M3CG, M3, TInt; 402c402,406 < PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type); --- > PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type; >???????????????? min_valid: BOOLEAN := FALSE; >???????????????? max_valid: BOOLEAN := FALSE; >???????????????? min: Target.Int := TInt.Zero; >???????????????? max: Target.Int := TInt.Zero); 414,415c418,423 < PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0); < (* == Load (v, o, t.size, t.align, t) *) --- > PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0; >???????????????????? min_valid: BOOLEAN := FALSE; >???????????????????? max_valid: BOOLEAN := FALSE; >???????????????????? min: Target.Int := TInt.Zero; >???????????????????? max: Target.Int := TInt.Zero); > (* == Load (v, o, t.size, t.align, t, min/max...) *) Index: m3-sys/m3front/src/misc/CG.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.m3,v retrieving revision 1.40 diff -r1.40 CG.m3 13c13 < IMPORT M3, M3CG, M3CG_Ops, M3CG_Check; --- > IMPORT M3, M3CG, M3CG_Ops, M3CG_Check, RTIO, RTParams; 45a46,49 >???? min_valid : BOOLEAN := FALSE; (* whether or not min is valid *) >???? max_valid : BOOLEAN := FALSE; (* whether or not max is valid *) >???? min?????? : Target.Int := TInt.Zero; (* the minimum possible value *) >???? max?????? : Target.Int := TInt.Zero; (* the maximum possible value *) 80c84,85 < VAR --- > VAR >?? debug := FALSE; 604a610,614 >???? v.min?????? := TInt.Zero; >???? v.max?????? := TInt.Zero; >???? v.min_valid := FALSE; >???? v.max_valid := FALSE; >? 766a777,780 >???? x.min?????? := TInt.Zero; >???? x.max?????? := TInt.Zero; >???? x.min_valid := FALSE; >???? x.max_valid := FALSE; 978a993,995 >?????? IF debug THEN >???????? RTIO.PutText("m3front:cg:Init_int:NOT in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); >?????? END; 980a998,1001 >???? END; >? >???? IF debug THEN >?????? RTIO.PutText("m3front:cg:Init_int:in_init: o: " & Fmt.Int(o) & " s:" & Fmt.Int(s) & " value:" & TInt.ToText(value) & "\n"); RTIO.Flush(); 1266c1287,1291 < PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type) = --- > PROCEDURE Load (v: Var;? o: Offset;? s: Size;? a: Alignment;? t: Type; >???????????????? min_valid: BOOLEAN := FALSE; >???????????????? max_valid: BOOLEAN := FALSE; >???????????????? min: Target.Int := TInt.Zero; >???????????????? max: Target.Int := TInt.Zero) = 1276c1301 ?????? SimpleLoad (v, o, t, min_valid, max_valid, min, max); 1291c1316 ???????? SimpleLoad (v, o, best_type, min_valid, max_valid, min, max); 1312c1337,1341 < PROCEDURE SimpleLoad (v: Var;? o: Offset;? t: Type) = --- > PROCEDURE SimpleLoad (v: Var;? o: Offset;? t: Type; >?????????????????????? min_valid: BOOLEAN := FALSE; >?????????????????????? max_valid: BOOLEAN := FALSE; >?????????????????????? min: Target.Int := TInt.Zero; >?????????????????????? max: Target.Int := TInt.Zero) = 1323a1353,1356 >?????? x.min_valid := min_valid; >?????? x.max_valid := max_valid; >?????? x.min?????? := min; >?????? x.max?????? := max; 1339a1373,1376 >?????? x.min?????? := TInt.Zero; >?????? x.max?????? := TInt.Zero; >?????? x.min_valid := FALSE; >?????? x.max_valid := FALSE; 1347a1385,1388 >???? stack[tos-1].min?????? := TInt.Zero; >???? stack[tos-1].max?????? := TInt.Zero; >???? stack[tos-1].min_valid := FALSE; >???? stack[tos-1].max_valid := FALSE; 1350c1391,1395 < PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0) = --- > PROCEDURE Load_int (t: IType;? v: Var;? o: Offset := 0; >???????????????????? min_valid: BOOLEAN := FALSE; >???????????????????? max_valid: BOOLEAN := FALSE; >???????????????????? min: Target.Int := TInt.Zero; >???????????????????? max: Target.Int := TInt.Zero) = 1352c1397 ???? SimpleLoad (v, o, t, min_valid, max_valid, min, max); 1815a1861,1864 >?????? x.min_valid := TRUE; >?????? x.max_valid := TRUE; >?????? x.min := i; >?????? x.max := i; 1832,1834c1881,2007 ?? VAR always_true: BOOLEAN; >?????? always_false: BOOLEAN; >?????? left_type: Type; >?????? right_type: Type; >?????? left_min: Target.Int; >?????? left_max: Target.Int; >?????? right_min: Target.Int; >?????? right_max: Target.Int; >?????? left_signed: BOOLEAN; >?????? right_signed: BOOLEAN; >?? BEGIN >? >???? always_true := FALSE; >???? always_false := FALSE; >? >???? WITH left? = stack [SCheck (2, "Compare-left")], >????????? right = stack [SCheck (1, "Compare-right")] DO >? >?????? left_type := left.type; >?????? right_type := right.type; >? >?????? IF????? left.min_valid >?????????? AND left.max_valid >?????????? AND right.min_valid >?????????? AND right.max_valid >?????????? AND Target.OrdinalType[left_type] >?????????? AND Target.OrdinalType[right_type] THEN >? >???????? left_min := left.min; >???????? left_max := left.max; >???????? right_min := right.min; >???????? right_max := right.max; >???????? left_signed := Target.SignedType[left_type]; >???????? right_signed := Target.SignedType[right_type]; >? >???????? (* First handle types that match in signedness. *) >? >???????? IF left_signed = right_signed THEN >? >?????????? (* Check for ranges with no overlap. *) >? >?????????? IF left_signed (* and right_signed *) THEN >???????????? IF TInt.LT(left_max, right_min) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; >???????????? ELSIF TInt.GT(left_min, right_max) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; >???????????? END; >?????????? ELSE (* left_signed and right_signed both false *) >???????????? IF TWord.LT(left_max, right_min) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; >???????????? ELSIF TWord.GT(left_min, right_max) THEN >?????????????? always_true := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; >???????????? END; >?????????? END; >? >?????????? (* Check for overlap just on the edge, e.g. [0..1] compared to [1..2]. *) >? >?????????? IF NOT (always_true OR always_false) THEN >???????????? IF TInt.EQ(left_max, right_min) THEN >?????????????? always_true := op = Cmp.LE; >?????????????? always_false := op = Cmp.GT; >???????????? ELSIF TInt.EQ(left_min, right_max) THEN >?????????????? always_true := op = Cmp.GE; >?????????????? always_false := op = Cmp.LT; >???????????? END; >?????????? END; >? >?????????? (* Handle equal subranges with one element, not likely to occur. *) >? >?????????? IF NOT (always_true OR always_false) THEN >???????????? IF????? TInt.EQ(left_max, left_min) >???????????????? AND TInt.EQ(left_max, right_max) >???????????????? AND TInt.EQ(left_max, right_min) THEN >?????????????? always_true? := op IN SET OF Cmp{Cmp.GE, Cmp.LE, Cmp.EQ}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.GT, Cmp.NE}; >???????????? END; >?????????? END; >???????? ELSE >? >?????????? (* Now deal with mixed up types (signed compared to unsigned). >??????????? * We may be able to merge these by setting some min/max >??????????? * to zero. That is, the minimum of an unsigned type is zero. >??????????? * However we want to be sure not to interpret unsigned min/max >??????????? * as signed. >??????????? *) >? >?????????? IF left_signed THEN >???????????? IF TInt.LT(left_max, TInt.Zero) THEN >?????????????? always_true? := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.EQ}; >???????????? ELSIF TInt.EQ(left_max, TInt.Zero) THEN >?????????????? always_true? := op = Cmp.LE; >?????????????? always_false := op = Cmp.GT; >???????????? END; >?????????? ELSE (* right is signed *) >???????????? IF TInt.LT(right_max, TInt.Zero) THEN >?????????????? always_true? := op IN SET OF Cmp{Cmp.GT, Cmp.GE, Cmp.NE}; >?????????????? always_false := op IN SET OF Cmp{Cmp.LT, Cmp.LE, Cmp.EQ}; >???????????? ELSIF TInt.EQ(right_max, TInt.Zero) THEN >?????????????? always_true := op = Cmp.GE; >?????????????? always_false := op = Cmp.LT; >???????????? END; >?????????? END; >???????? END; >?????? END; >?? >?????? <* ASSERT NOT (always_true AND always_false) *> >? >?????? IF always_true OR always_false THEN >???????? Discard(right_type); >???????? Discard(left_type); >???????? IF always_true THEN >?????????? cg.load_integer (Target.Integer.cg_type, TInt.One); >???????? ELSE >?????????? cg.load_integer (Target.Integer.cg_type, TInt.Zero); >???????? END >?????? ELSE >???????? IF Force_pair (commute := TRUE) THEN >?????????? op := M3CG.SwappedCompare [op]; >???????? END; >???????? cg.compare (t, Target.Integer.cg_type, op); >???????? SPop (2, "Compare"); >?????? END; 1836,1837d2008 ?????? x.min?????? := TInt.Zero; >?????? x.max?????? := TInt.Zero; >?????? x.min_valid := FALSE; >?????? x.max_valid := FALSE; 2977c3152,3153 < BEGIN --- > BEGIN >?? debug := debug OR RTParams.IsPresent ("m3front_cg_debug"); Index: m3-sys/m3front/src/values/Variable.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3front/src/values/Variable.m3,v retrieving revision 1.13 diff -r1.13 Variable.m3 362a363,365 >?? VAR min: Target.Int; >?????? max: Target.Int; >?????? bounds_valid: BOOLEAN; 395c398,401 ???????? (*GetBounds (t, min, max); >???????? bounds_valid := TInt.LE(min, max);*) >???????? bounds_valid := t.tipe # NIL AND Type.GetBounds(t.tipe, min, max) AND TInt.LE(min, max); >???????? CG.Load (t.cg_var, t.offset, t.size, t.cg_align, t.stk_type, bounds_valid, bounds_valid, min, max); -------------- next part -------------- An HTML attachment was scrubbed... URL: From rodney_bates at lcwb.coop Tue May 24 02:16:18 2011 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Mon, 23 May 2011 19:16:18 -0500 Subject: [M3devel] range analysis? In-Reply-To: <20110523225302.GA8980@topoi.pooq.com> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> <4DDA8F1A.3070207@lcwb.coop> <8C9E1E77-686F-42E0-87FA-B573A4A02CC9@cs.purdue.edu> <4DDAA6EC.8060401@lcwb.coop> <20110523225302.GA8980@topoi.pooq.com> Message-ID: <4DDAF8D2.2090800@lcwb.coop> On 05/23/2011 05:53 PM, Hendrik Boom wrote: > On Mon, May 23, 2011 at 01:26:52PM -0500, Rodney M. Bates wrote: >> This needs more thought. On the one hand, 2.2.3 on array types allows >> the explicit element type in either kind of array type definition to >> be empty, > > Well, the array might be empty, in which case no nonexistent values > would be required when the array is created. Good point. Right now, the compiler does not allow creation of such arrays, either fixed or open. The error messages both refer to the _array type_ whose elements also have empty type as an "empty type", regardless of whether the element count is zero or positive. > >> unlike the way 2.2.4 on record types requires a field type >> to be nonempty. >> >> On the other hand, 2.2 has a general prohibition against declaring a >> variable of empty type, and it is all over the language spec that the >> elements of arrays are "variables". The general definition of variable >> in 2.1 would apply to array elements. Thre are numerous places that >> describe things that can be done with a variable that we all informally >> know can be done to an element, as it should be and we all have done >> many times. Moreover, 2.2.3 says in the first paragraph that the >> elements are variables. >> >> So here, the compiler is too liberal, and the language would be clearer >> with an explicit rule against empty element types. >> >> I haven't spotted anywhere a parameter is specifically called a variable, >> and it is not required to have a nonempty type in the description of >> parameter declarations. However, it certainly seems to me to fit >> the definition of variable, and as above, there are lots of things >> we know can be done with it that the language simply describes as >> doable to a variable. Moreover, for every mode, there is a rule >> that at call time, the formal is "bound to" a variable, which pretty >> well makes it variable in any context where it can be used. Even in >> a keyword binding, we are getting ready to bind it to a variable >> very soon. >> >> So maybe we need to 1) say a formal parameter is a variable, and >> 2) say the type in a parameter declaration must be nonempty. >> >> The language definition is also full of an ambiguity in its use >> of "variable" that I have been bothered by in talking about programming >> languages in general for years. One meaning is the meaning I have been >> talking about, The other is the kind of variable that is declared by a >> VAR declaration (not a VAR parameter). There are some uses in the >> language that I think need to have this latter meaning in order to be right. >> >> So we need a different or qualified term for this narrower meaning. >> >> On 05/23/2011 11:54 AM, Tony Hosking wrote: >>> >>> On May 23, 2011, at 12:45 PM, Rodney M. Bates wrote: >>> >>>> On 05/23/2011 09:31 AM, Tony Hosking wrote: >>>>> An empty subrange gives a warning in the compiler. >>>> >>>> By my experiments, empty subrange, empty enumeration, and arrays >>>> thereof don't warn. >>> >>> Sorry yes, you're right. But usage to declare any variable does. >>> >>>> >>>>> But, the semantics is that it is empty, and has no values of the type. >>>>> You cannot allocate (NEW) an empty type. >>>>> You cannot declare a field of empty type. >>>> >>>> It seems odd that we have this rule for fields, but no corresponding >>>> prohibition against arrays with empty element types. By experiments, >>>> cm3 allows this, for both fixed and open arrays, but treats such array >>>> types as empty types, something the language also does not say. >>>> >>>> At the least, the language and the compiler should agree with each other. >>>> Maybe records/objects and arrays should be treated consistently here? >>> >>> Yes, I suppose so. >>> >>>>> Nor can you declare a variable of empty type. >>>> >>>> Again, oddly, there is no such prohibition in the language against >>>> declaring a formal parameter of empty type. Cm3 prohibits it, >>>> and calls it a 'variable' in the error message. >>> >>> You're right, though it's not the parameter that errors but the variable associated with the parameter. >>> >>>> Again, language and compiler should agree. >>> >>> Can you point me to the relevant entries in the language spec? >>> >>>> >>>> The language also prohibits applying FIRST and LAST to the empty >>>> enumeration, but they are OK applied to an empty subrange. >>>> This makes sense, because they return values of the base type >>>> of the argument type, and such values exist for an empty subrange >>>> but not the empty enumeration, whose base type is only itself. >>>> >>>>> >>>>> On May 23, 2011, at 8:41 AM, Hendrik Boom wrote: >>>>> >>>>>> On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: >>>>>>> >>>>>>> Well, I can build the whole tree and see how many times it helps. >>>>>>> I think this is a pretty standard optimization technique. >>>>>>> Though it'd work better with compiler-derived additional information. >>>>>>> >>>>>>> I initially happened upon this idea developing test cases. >>>>>>> >>>>>>>> The code assumes the minimum of a type is less than or equal to its maximum. >>>>>>> >>>>>>> I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. >>>>>> >>>>>> What *is* the semantics of a range whose minimum is greater than its >>>>>> maximum? There plainly can't be any values in this range. How is a >>>>>> variable of this tyoe initialized? Not to some arbitrary value of the >>>>>> type, because there aren't any. I can see this type being useful to >>>>>> admit convenient generalizations -- for example, an array with n >>>>>> elements can still exist if n happens to be zero, but it seems to me >>>>>> that any code involving a value of the range for subscripts for this >>>>>> array must be simple unexecutable. >>>>>> >>>>>> Or is there some latitude available in the principle that a value of a >>>>>> variable must always be of the correct type? >>>>>> >>>>>> -- hendrik >>>>> >>>>> >>> >>> > From hosking at cs.purdue.edu Tue May 24 04:04:18 2011 From: hosking at cs.purdue.edu (Tony Hosking) Date: Mon, 23 May 2011 22:04:18 -0400 Subject: [M3devel] range analysis? In-Reply-To: <20110523225302.GA8980@topoi.pooq.com> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> <4DDA8F1A.3070207@lcwb.coop> <8C9E1E77-686F-42E0-87FA-B573A4A02CC9@cs.purdue.edu> <4DDAA6EC.8060401@lcwb.coop> <20110523225302.GA8980@topoi.pooq.com> Message-ID: On May 23, 2011, at 6:53 PM, Hendrik Boom wrote: > On Mon, May 23, 2011 at 01:26:52PM -0500, Rodney M. Bates wrote: >> This needs more thought. On the one hand, 2.2.3 on array types allows >> the explicit element type in either kind of array type definition to >> be empty, > > Well, the array might be empty, in which case no nonexistent values > would be required when the array is created. You cannot instantiate an empty array type. > >> unlike the way 2.2.4 on record types requires a field type >> to be nonempty. >> >> On the other hand, 2.2 has a general prohibition against declaring a >> variable of empty type, and it is all over the language spec that the >> elements of arrays are "variables". The general definition of variable >> in 2.1 would apply to array elements. Thre are numerous places that >> describe things that can be done with a variable that we all informally >> know can be done to an element, as it should be and we all have done >> many times. Moreover, 2.2.3 says in the first paragraph that the >> elements are variables. >> >> So here, the compiler is too liberal, and the language would be clearer >> with an explicit rule against empty element types. >> >> I haven't spotted anywhere a parameter is specifically called a variable, >> and it is not required to have a nonempty type in the description of >> parameter declarations. However, it certainly seems to me to fit >> the definition of variable, and as above, there are lots of things >> we know can be done with it that the language simply describes as >> doable to a variable. Moreover, for every mode, there is a rule >> that at call time, the formal is "bound to" a variable, which pretty >> well makes it variable in any context where it can be used. Even in >> a keyword binding, we are getting ready to bind it to a variable >> very soon. >> >> So maybe we need to 1) say a formal parameter is a variable, and >> 2) say the type in a parameter declaration must be nonempty. >> >> The language definition is also full of an ambiguity in its use >> of "variable" that I have been bothered by in talking about programming >> languages in general for years. One meaning is the meaning I have been >> talking about, The other is the kind of variable that is declared by a >> VAR declaration (not a VAR parameter). There are some uses in the >> language that I think need to have this latter meaning in order to be right. >> >> So we need a different or qualified term for this narrower meaning. >> >> On 05/23/2011 11:54 AM, Tony Hosking wrote: >>> >>> On May 23, 2011, at 12:45 PM, Rodney M. Bates wrote: >>> >>>> On 05/23/2011 09:31 AM, Tony Hosking wrote: >>>>> An empty subrange gives a warning in the compiler. >>>> >>>> By my experiments, empty subrange, empty enumeration, and arrays >>>> thereof don't warn. >>> >>> Sorry yes, you're right. But usage to declare any variable does. >>> >>>> >>>>> But, the semantics is that it is empty, and has no values of the type. >>>>> You cannot allocate (NEW) an empty type. >>>>> You cannot declare a field of empty type. >>>> >>>> It seems odd that we have this rule for fields, but no corresponding >>>> prohibition against arrays with empty element types. By experiments, >>>> cm3 allows this, for both fixed and open arrays, but treats such array >>>> types as empty types, something the language also does not say. >>>> >>>> At the least, the language and the compiler should agree with each other. >>>> Maybe records/objects and arrays should be treated consistently here? >>> >>> Yes, I suppose so. >>> >>>>> Nor can you declare a variable of empty type. >>>> >>>> Again, oddly, there is no such prohibition in the language against >>>> declaring a formal parameter of empty type. Cm3 prohibits it, >>>> and calls it a 'variable' in the error message. >>> >>> You're right, though it's not the parameter that errors but the variable associated with the parameter. >>> >>>> Again, language and compiler should agree. >>> >>> Can you point me to the relevant entries in the language spec? >>> >>>> >>>> The language also prohibits applying FIRST and LAST to the empty >>>> enumeration, but they are OK applied to an empty subrange. >>>> This makes sense, because they return values of the base type >>>> of the argument type, and such values exist for an empty subrange >>>> but not the empty enumeration, whose base type is only itself. >>>> >>>>> >>>>> On May 23, 2011, at 8:41 AM, Hendrik Boom wrote: >>>>> >>>>>> On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: >>>>>>> >>>>>>> Well, I can build the whole tree and see how many times it helps. >>>>>>> I think this is a pretty standard optimization technique. >>>>>>> Though it'd work better with compiler-derived additional information. >>>>>>> >>>>>>> I initially happened upon this idea developing test cases. >>>>>>> >>>>>>>> The code assumes the minimum of a type is less than or equal to its maximum. >>>>>>> >>>>>>> I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. >>>>>> >>>>>> What *is* the semantics of a range whose minimum is greater than its >>>>>> maximum? There plainly can't be any values in this range. How is a >>>>>> variable of this tyoe initialized? Not to some arbitrary value of the >>>>>> type, because there aren't any. I can see this type being useful to >>>>>> admit convenient generalizations -- for example, an array with n >>>>>> elements can still exist if n happens to be zero, but it seems to me >>>>>> that any code involving a value of the range for subscripts for this >>>>>> array must be simple unexecutable. >>>>>> >>>>>> Or is there some latitude available in the principle that a value of a >>>>>> variable must always be of the correct type? >>>>>> >>>>>> -- hendrik >>>>> >>>>> >>> >>> From hosking at cs.purdue.edu Tue May 24 04:04:40 2011 From: hosking at cs.purdue.edu (Tony Hosking) Date: Mon, 23 May 2011 22:04:40 -0400 Subject: [M3devel] range analysis? In-Reply-To: <20110523225508.GB8980@topoi.pooq.com> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> <4DDA8F1A.3070207@lcwb.coop> <8C9E1E77-686F-42E0-87FA-B573A4A02CC9@cs.purdue.edu> <4DDAA6EC.8060401@lcwb.coop> <45B5D160-9E80-4BB9-8411-F3976BCDC207@cs.purdue.edu> <20110523225508.GB8980@topoi.pooq.com> Message-ID: <67872FDF-2DF6-43D5-8CCD-F1E4644CA2A6@cs.purdue.edu> Element type. On May 23, 2011, at 6:55 PM, Hendrik Boom wrote: > On Mon, May 23, 2011 at 02:45:37PM -0400, Tony Hosking wrote: >> >> On May 23, 2011, at 2:26 PM, Rodney M. Bates wrote: >> >>> This needs more thought. On the one hand, 2.2.3 on array types allows >>> the explicit element type in either kind of array type definition to >>> be empty, unlike the way 2.2.4 on record types requires a field type >>> to be nonempty. >> >> I note that an array type of empty elements is itself empty and cannot be instantiated. >> >>> On the other hand, 2.2 has a general prohibition against declaring a >>> variable of empty type, and it is all over the language spec that the >>> elements of arrays are "variables". The general definition of variable >>> in 2.1 would apply to array elements. Thre are numerous places that >>> describe things that can be done with a variable that we all informally >>> know can be done to an element, as it should be and we all have done >>> many times. Moreover, 2.2.3 says in the first paragraph that the >>> elements are variables. >> >> So, it seems to me that we could simply disallow empty array elements and be within spec. > > You mean the array elements are empty? or that the element type is > empty? These are very different concepts. From hosking at cs.purdue.edu Tue May 24 04:06:34 2011 From: hosking at cs.purdue.edu (Tony Hosking) Date: Mon, 23 May 2011 22:06:34 -0400 Subject: [M3devel] range analysis? In-Reply-To: <4DDAF56D.8010505@lcwb.coop> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> <4DDA8F1A.3070207@lcwb.coop> <8C9E1E77-686F-42E0-87FA-B573A4A02CC9@cs.purdue.edu> <4DDAA6EC.8060401@lcwb.coop> <45B5D160-9E80-4BB9-8411-F3976BCDC207@cs.purdue.edu> <4DDAF56D.8010505@lcwb.coop> Message-ID: <919256C9-1773-43EC-9B62-C45883935957@cs.purdue.edu> Sorry for the terse response. Is there a proposal buried in there? On May 23, 2011, at 8:01 PM, Rodney M. Bates wrote: > > > On 05/23/2011 01:45 PM, Tony Hosking wrote: >> >> On May 23, 2011, at 2:26 PM, Rodney M. Bates wrote: >> >>> This needs more thought. On the one hand, 2.2.3 on array types allows >>> the explicit element type in either kind of array type definition to >>> be empty, unlike the way 2.2.4 on record types requires a field type >>> to be nonempty. >> >> I note that an array type of empty elements is itself empty and cannot be instantiated. >> > > Yes. > >>> On the other hand, 2.2 has a general prohibition against declaring a >>> variable of empty type, and it is all over the language spec that the >>> elements of arrays are "variables". The general definition of variable >>> in 2.1 would apply to array elements. Thre are numerous places that >>> describe things that can be done with a variable that we all informally >>> know can be done to an element, as it should be and we all have done >>> many times. Moreover, 2.2.3 says in the first paragraph that the >>> elements are variables. >> >> So, it seems to me that we could simply disallow empty array elements and be within spec. > > I agree. > >> >>> So here, the compiler is too liberal, and the language would be clearer >>> with an explicit rule against empty element types. >> >> Right. >> >>> I haven't spotted anywhere a parameter is specifically called a variable, >>> and it is not required to have a nonempty type in the description of >>> parameter declarations. However, it certainly seems to me to fit >>> the definition of variable, and as above, there are lots of things >>> we know can be done with it that the language simply describes as >>> doable to a variable. Moreover, for every mode, there is a rule >>> that at call time, the formal is "bound to" a variable, which pretty >>> well makes it variable in any context where it can be used. Even in >>> a keyword binding, we are getting ready to bind it to a variable >>> very soon. >> >> Right. >> >>> So maybe we need to 1) say a formal parameter is a variable, and >> >> A formal parameter is not in itself a variable. It's part of a type (the signature) not an implementation of that type. But every formal parameter has a corresponding variable in the body of the procedure that implements a given signature. >> >>> 2) say the type in a parameter declaration must be nonempty. >> >> This seems overwrought. I would stop simply at the variables (not the types) and let the binding of formal parameters to variables take care of the check as it currently does. >> > > My first thought was that this argument is no more or less applicable to > a procedure type containing a formal of empty type than to a record > type containing a field (which is currently defined as a variable) > of empty type. Both are just types constructed from other type(s), > to be maybe instantiated later. In the case of the record, we now > disallow the type to be constructed. Your proposal would inconsistently > allow the procedure type to be constructed but complain when an > attempt is made to instantiate it (i.e., call it) later. > > My second thought was that a procedure type with empty-typed formal > is not an empty type, because it contains the perfectly legitimate > value NIL, which of course, you can't call anyway, thus avoiding the > issue of instantiating the formal. This is an essential difference > that would justify doing it differently for records and procedures. > > My third thought is whereas you might consider such a procedure _type_ > to have just one value, if you allow the signature in a procedure > _constant_ (i.e., an ordinary procedure declaration) to have an > empty-typed formal, you now have a value of this procedure type > other than NIL. In fact, the number of such possible values is > unbounded. Does such a procedure value make any more sense than a > value of a record with an empty-typed field? > > Right now, the compiler allows the procedure type with empty-typed > formal, a variable of that type, and assignment of NIL to the variable. > But the compiler disallows the empty-typed formal in a procedure constant > (and calls the formal a "variable" in its error message.) This seems > sensible enough to me, and I suggest we document the illegality of the > signature in a procedure constant. We could only call the formal a > variable when in the signature of a procedure constant, not a procedure > type definition, otherwise the procedure type would be illegal too. > >>> The language definition is also full of an ambiguity in its use >>> of "variable" that I have been bothered by in talking about programming >>> languages in general for years. One meaning is the meaning I have been >>> talking about, The other is the kind of variable that is declared by a >>> VAR declaration (not a VAR parameter). There are some uses in the >>> language that I think need to have this latter meaning in order to be right. >> >> Can you enumerate? >> > > Yeah, but not this minute. > >>> So we need a different or qualified term for this narrower meaning. >>> >>> On 05/23/2011 11:54 AM, Tony Hosking wrote: >>>> >>>> On May 23, 2011, at 12:45 PM, Rodney M. Bates wrote: >>>> >>>>> On 05/23/2011 09:31 AM, Tony Hosking wrote: >>>>>> An empty subrange gives a warning in the compiler. >>>>> >>>>> By my experiments, empty subrange, empty enumeration, and arrays >>>>> thereof don't warn. >>>> >>>> Sorry yes, you're right. But usage to declare any variable does. >>>> >>>>> >>>>>> But, the semantics is that it is empty, and has no values of the type. >>>>>> You cannot allocate (NEW) an empty type. >>>>>> You cannot declare a field of empty type. >>>>> >>>>> It seems odd that we have this rule for fields, but no corresponding >>>>> prohibition against arrays with empty element types. By experiments, >>>>> cm3 allows this, for both fixed and open arrays, but treats such array >>>>> types as empty types, something the language also does not say. >>>>> >>>>> At the least, the language and the compiler should agree with each other. >>>>> Maybe records/objects and arrays should be treated consistently here? >>>> >>>> Yes, I suppose so. >>>> >>>>>> Nor can you declare a variable of empty type. >>>>> >>>>> Again, oddly, there is no such prohibition in the language against >>>>> declaring a formal parameter of empty type. Cm3 prohibits it, >>>>> and calls it a 'variable' in the error message. >>>> >>>> You're right, though it's not the parameter that errors but the variable associated with the parameter. >>>> >>>>> Again, language and compiler should agree. >>>> >>>> Can you point me to the relevant entries in the language spec? >>>> >>>>> >>>>> The language also prohibits applying FIRST and LAST to the empty >>>>> enumeration, but they are OK applied to an empty subrange. >>>>> This makes sense, because they return values of the base type >>>>> of the argument type, and such values exist for an empty subrange >>>>> but not the empty enumeration, whose base type is only itself. >>>>> >>>>>> >>>>>> On May 23, 2011, at 8:41 AM, Hendrik Boom wrote: >>>>>> >>>>>>> On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: >>>>>>>> >>>>>>>> Well, I can build the whole tree and see how many times it helps. >>>>>>>> I think this is a pretty standard optimization technique. >>>>>>>> Though it'd work better with compiler-derived additional information. >>>>>>>> >>>>>>>> I initially happened upon this idea developing test cases. >>>>>>>> >>>>>>>>> The code assumes the minimum of a type is less than or equal to its maximum. >>>>>>>> >>>>>>>> I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. >>>>>>> >>>>>>> What *is* the semantics of a range whose minimum is greater than its >>>>>>> maximum? There plainly can't be any values in this range. How is a >>>>>>> variable of this tyoe initialized? Not to some arbitrary value of the >>>>>>> type, because there aren't any. I can see this type being useful to >>>>>>> admit convenient generalizations -- for example, an array with n >>>>>>> elements can still exist if n happens to be zero, but it seems to me >>>>>>> that any code involving a value of the range for subscripts for this >>>>>>> array must be simple unexecutable. >>>>>>> >>>>>>> Or is there some latitude available in the principle that a value of a >>>>>>> variable must always be of the correct type? >>>>>>> >>>>>>> -- hendrik >>>>>> >>>>>> >>>> >>>> >> >> From rodney_bates at lcwb.coop Tue May 24 22:14:59 2011 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Tue, 24 May 2011 15:14:59 -0500 Subject: [M3devel] range analysis? Message-ID: <4DDC11C3.8090303@lcwb.coop> On 05/23/2011 01:45 PM, Tony Hosking wrote: > > On May 23, 2011, at 2:26 PM, Rodney M. Bates wrote: > >> This needs more thought. On the one hand, 2.2.3 on array types allows >> the explicit element type in either kind of array type definition to >> be empty, unlike the way 2.2.4 on record types requires a field type >> to be nonempty. > > I note that an array type of empty elements is itself empty and cannot be instantiated. > Yes. >> On the other hand, 2.2 has a general prohibition against declaring a >> variable of empty type, and it is all over the language spec that the >> elements of arrays are "variables". The general definition of variable >> in 2.1 would apply to array elements. Thre are numerous places that >> describe things that can be done with a variable that we all informally >> know can be done to an element, as it should be and we all have done >> many times. Moreover, 2.2.3 says in the first paragraph that the >> elements are variables. > > So, it seems to me that we could simply disallow empty array elements and be within spec. I agree. > >> So here, the compiler is too liberal, and the language would be clearer >> with an explicit rule against empty element types. > > Right. > >> I haven't spotted anywhere a parameter is specifically called a variable, >> and it is not required to have a nonempty type in the description of >> parameter declarations. However, it certainly seems to me to fit >> the definition of variable, and as above, there are lots of things >> we know can be done with it that the language simply describes as >> doable to a variable. Moreover, for every mode, there is a rule >> that at call time, the formal is "bound to" a variable, which pretty >> well makes it variable in any context where it can be used. Even in >> a keyword binding, we are getting ready to bind it to a variable >> very soon. > > Right. > >> So maybe we need to 1) say a formal parameter is a variable, and > > A formal parameter is not in itself a variable. It's part of a type (the signature) not an implementation of that type. But every formal parameter has a corresponding variable in the body of the procedure that implements a given signature. > >> 2) say the type in a parameter declaration must be nonempty. > > This seems overwrought. I would stop simply at the variables (not the types) and let the binding of formal parameters to variables take care of the check as it currently does. > My first thought was that this argument is no more or less applicable to a procedure type containing a formal of empty type than to a record type containing a field (which is currently defined as a variable) of empty type. Both are just types constructed from other type(s), to be maybe instantiated later. In the case of the record, we now disallow the type to be constructed. Your proposal would inconsistently allow the procedure type to be constructed but complain when an attempt is made to instantiate it (i.e., call it) later. My second thought was that a procedure type with empty-typed formal is not an empty type, because it contains the perfectly legitimate value NIL, which of course, you can't call anyway, thus avoiding the issue of instantiating the formal. This is an essential difference that would justify doing it differently for records and procedures. My third thought is whereas you might consider such a procedure _type_ to have just one value, if you allow the signature in a procedure _constant_ (i.e., an ordinary procedure declaration) to have an empty-typed formal, you now have a value of this procedure type other than NIL. In fact, the number of such possible values is unbounded. Does such a procedure value make any more sense than a value of a record with an empty-typed field? Right now, the compiler allows the procedure type with empty-typed formal, a variable of that type, and assignment of NIL to the variable. But the compiler disallows the empty-typed formal in a procedure constant (and calls the formal a "variable" in its error message.) This seems sensible enough to me, and I suggest we document the illegality of the signature in a procedure constant. We could only call the formal a variable when in the signature of a procedure constant, not a procedure type definition, otherwise the procedure type would be illegal too. >> The language definition is also full of an ambiguity in its use >> of "variable" that I have been bothered by in talking about programming >> languages in general for years. One meaning is the meaning I have been >> talking about, The other is the kind of variable that is declared by a >> VAR declaration (not a VAR parameter). There are some uses in the >> language that I think need to have this latter meaning in order to be right. > > Can you enumerate? > Yeah, but not this minute. >> So we need a different or qualified term for this narrower meaning. >> >> On 05/23/2011 11:54 AM, Tony Hosking wrote: >>> >>> On May 23, 2011, at 12:45 PM, Rodney M. Bates wrote: >>> >>>> On 05/23/2011 09:31 AM, Tony Hosking wrote: >>>>> An empty subrange gives a warning in the compiler. >>>> >>>> By my experiments, empty subrange, empty enumeration, and arrays >>>> thereof don't warn. >>> >>> Sorry yes, you're right. But usage to declare any variable does. >>> >>>> >>>>> But, the semantics is that it is empty, and has no values of the type. >>>>> You cannot allocate (NEW) an empty type. >>>>> You cannot declare a field of empty type. >>>> >>>> It seems odd that we have this rule for fields, but no corresponding >>>> prohibition against arrays with empty element types. By experiments, >>>> cm3 allows this, for both fixed and open arrays, but treats such array >>>> types as empty types, something the language also does not say. >>>> >>>> At the least, the language and the compiler should agree with each other. >>>> Maybe records/objects and arrays should be treated consistently here? >>> >>> Yes, I suppose so. >>> >>>>> Nor can you declare a variable of empty type. >>>> >>>> Again, oddly, there is no such prohibition in the language against >>>> declaring a formal parameter of empty type. Cm3 prohibits it, >>>> and calls it a 'variable' in the error message. >>> >>> You're right, though it's not the parameter that errors but the variable associated with the parameter. >>> >>>> Again, language and compiler should agree. >>> >>> Can you point me to the relevant entries in the language spec? >>> >>>> >>>> The language also prohibits applying FIRST and LAST to the empty >>>> enumeration, but they are OK applied to an empty subrange. >>>> This makes sense, because they return values of the base type >>>> of the argument type, and such values exist for an empty subrange >>>> but not the empty enumeration, whose base type is only itself. >>>> >>>>> >>>>> On May 23, 2011, at 8:41 AM, Hendrik Boom wrote: >>>>> >>>>>> On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: >>>>>>> >>>>>>> Well, I can build the whole tree and see how many times it helps. >>>>>>> I think this is a pretty standard optimization technique. >>>>>>> Though it'd work better with compiler-derived additional information. >>>>>>> >>>>>>> I initially happened upon this idea developing test cases. >>>>>>> >>>>>>>> The code assumes the minimum of a type is less than or equal to its maximum. >>>>>>> >>>>>>> I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. >>>>>> >>>>>> What *is* the semantics of a range whose minimum is greater than its >>>>>> maximum? There plainly can't be any values in this range. How is a >>>>>> variable of this tyoe initialized? Not to some arbitrary value of the >>>>>> type, because there aren't any. I can see this type being useful to >>>>>> admit convenient generalizations -- for example, an array with n >>>>>> elements can still exist if n happens to be zero, but it seems to me >>>>>> that any code involving a value of the range for subscripts for this >>>>>> array must be simple unexecutable. >>>>>> >>>>>> Or is there some latitude available in the principle that a value of a >>>>>> variable must always be of the correct type? >>>>>> >>>>>> -- hendrik >>>>> >>>>> >>> >>> > From mika at async.caltech.edu Tue May 24 22:21:50 2011 From: mika at async.caltech.edu (Mika Nystrom) Date: Tue, 24 May 2011 13:21:50 -0700 Subject: [M3devel] range analysis? In-Reply-To: <4DDC11C3.8090303@lcwb.coop> References: <4DDC11C3.8090303@lcwb.coop> Message-ID: <20110524202150.5B4711A2078@async.async.caltech.edu> "Rodney M. Bates" writes: ... > >My first thought was that this argument is no more or less applicable to >a procedure type containing a formal of empty type than to a record >type containing a field (which is currently defined as a variable) >of empty type. Both are just types constructed from other type(s), >to be maybe instantiated later. In the case of the record, we now >disallow the type to be constructed. Your proposal would inconsistently >allow the procedure type to be constructed but complain when an >attempt is made to instantiate it (i.e., call it) later. > >My second thought was that a procedure type with empty-typed formal >is not an empty type, because it contains the perfectly legitimate >value NIL, which of course, you can't call anyway, thus avoiding the >issue of instantiating the formal. This is an essential difference >that would justify doing it differently for records and procedures. > By this logic, shoudln't you also allow such types to be fields in OBJECT types? What about REF RECORD types? Mika From rodney_bates at lcwb.coop Wed May 25 16:54:01 2011 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Wed, 25 May 2011 09:54:01 -0500 Subject: [M3devel] range analysis? In-Reply-To: <919256C9-1773-43EC-9B62-C45883935957@cs.purdue.edu> References: <60856C0A-50DC-4BA5-AB94-639B4B75ED21@cs.purdue.edu> <20110523124153.GA31229@topoi.pooq.com> <70AA1A1B-7C19-4202-912D-DD2142A2F5F4@cs.purdue.edu> <4DDA8F1A.3070207@lcwb.coop> <8C9E1E77-686F-42E0-87FA-B573A4A02CC9@cs.purdue.edu> <4DDAA6EC.8060401@lcwb.coop> <45B5D160-9E80-4BB9-8411-F3976BCDC207@cs.purdue.edu> <4DDAF56D.8010505@lcwb.coop> <919256C9-1773-43EC-9B62-C45883935957@cs.purdue.edu> Message-ID: <4DDD1809.3030108@lcwb.coop> Yes. Keep the current behavior of the compiler (formal with empty-type is legal in a procedure type, but not in a procedure constant) and document it. On 05/23/2011 09:06 PM, Tony Hosking wrote: > Sorry for the terse response. Is there a proposal buried in there? > > On May 23, 2011, at 8:01 PM, Rodney M. Bates wrote: > >> >> >> On 05/23/2011 01:45 PM, Tony Hosking wrote: >>> >>> On May 23, 2011, at 2:26 PM, Rodney M. Bates wrote: >>> >>>> This needs more thought. On the one hand, 2.2.3 on array types allows >>>> the explicit element type in either kind of array type definition to >>>> be empty, unlike the way 2.2.4 on record types requires a field type >>>> to be nonempty. >>> >>> I note that an array type of empty elements is itself empty and cannot be instantiated. >>> >> >> Yes. >> >>>> On the other hand, 2.2 has a general prohibition against declaring a >>>> variable of empty type, and it is all over the language spec that the >>>> elements of arrays are "variables". The general definition of variable >>>> in 2.1 would apply to array elements. Thre are numerous places that >>>> describe things that can be done with a variable that we all informally >>>> know can be done to an element, as it should be and we all have done >>>> many times. Moreover, 2.2.3 says in the first paragraph that the >>>> elements are variables. >>> >>> So, it seems to me that we could simply disallow empty array elements and be within spec. >> >> I agree. >> >>> >>>> So here, the compiler is too liberal, and the language would be clearer >>>> with an explicit rule against empty element types. >>> >>> Right. >>> >>>> I haven't spotted anywhere a parameter is specifically called a variable, >>>> and it is not required to have a nonempty type in the description of >>>> parameter declarations. However, it certainly seems to me to fit >>>> the definition of variable, and as above, there are lots of things >>>> we know can be done with it that the language simply describes as >>>> doable to a variable. Moreover, for every mode, there is a rule >>>> that at call time, the formal is "bound to" a variable, which pretty >>>> well makes it variable in any context where it can be used. Even in >>>> a keyword binding, we are getting ready to bind it to a variable >>>> very soon. >>> >>> Right. >>> >>>> So maybe we need to 1) say a formal parameter is a variable, and >>> >>> A formal parameter is not in itself a variable. It's part of a type (the signature) not an implementation of that type. But every formal parameter has a corresponding variable in the body of the procedure that implements a given signature. >>> >>>> 2) say the type in a parameter declaration must be nonempty. >>> >>> This seems overwrought. I would stop simply at the variables (not the types) and let the binding of formal parameters to variables take care of the check as it currently does. >>> >> >> My first thought was that this argument is no more or less applicable to >> a procedure type containing a formal of empty type than to a record >> type containing a field (which is currently defined as a variable) >> of empty type. Both are just types constructed from other type(s), >> to be maybe instantiated later. In the case of the record, we now >> disallow the type to be constructed. Your proposal would inconsistently >> allow the procedure type to be constructed but complain when an >> attempt is made to instantiate it (i.e., call it) later. >> >> My second thought was that a procedure type with empty-typed formal >> is not an empty type, because it contains the perfectly legitimate >> value NIL, which of course, you can't call anyway, thus avoiding the >> issue of instantiating the formal. This is an essential difference >> that would justify doing it differently for records and procedures. >> >> My third thought is whereas you might consider such a procedure _type_ >> to have just one value, if you allow the signature in a procedure >> _constant_ (i.e., an ordinary procedure declaration) to have an >> empty-typed formal, you now have a value of this procedure type >> other than NIL. In fact, the number of such possible values is >> unbounded. Does such a procedure value make any more sense than a >> value of a record with an empty-typed field? >> >> Right now, the compiler allows the procedure type with empty-typed >> formal, a variable of that type, and assignment of NIL to the variable. >> But the compiler disallows the empty-typed formal in a procedure constant >> (and calls the formal a "variable" in its error message.) This seems >> sensible enough to me, and I suggest we document the illegality of the >> signature in a procedure constant. We could only call the formal a >> variable when in the signature of a procedure constant, not a procedure >> type definition, otherwise the procedure type would be illegal too. >> >>>> The language definition is also full of an ambiguity in its use >>>> of "variable" that I have been bothered by in talking about programming >>>> languages in general for years. One meaning is the meaning I have been >>>> talking about, The other is the kind of variable that is declared by a >>>> VAR declaration (not a VAR parameter). There are some uses in the >>>> language that I think need to have this latter meaning in order to be right. >>> >>> Can you enumerate? >>> >> >> Yeah, but not this minute. >> >>>> So we need a different or qualified term for this narrower meaning. >>>> >>>> On 05/23/2011 11:54 AM, Tony Hosking wrote: >>>>> >>>>> On May 23, 2011, at 12:45 PM, Rodney M. Bates wrote: >>>>> >>>>>> On 05/23/2011 09:31 AM, Tony Hosking wrote: >>>>>>> An empty subrange gives a warning in the compiler. >>>>>> >>>>>> By my experiments, empty subrange, empty enumeration, and arrays >>>>>> thereof don't warn. >>>>> >>>>> Sorry yes, you're right. But usage to declare any variable does. >>>>> >>>>>> >>>>>>> But, the semantics is that it is empty, and has no values of the type. >>>>>>> You cannot allocate (NEW) an empty type. >>>>>>> You cannot declare a field of empty type. >>>>>> >>>>>> It seems odd that we have this rule for fields, but no corresponding >>>>>> prohibition against arrays with empty element types. By experiments, >>>>>> cm3 allows this, for both fixed and open arrays, but treats such array >>>>>> types as empty types, something the language also does not say. >>>>>> >>>>>> At the least, the language and the compiler should agree with each other. >>>>>> Maybe records/objects and arrays should be treated consistently here? >>>>> >>>>> Yes, I suppose so. >>>>> >>>>>>> Nor can you declare a variable of empty type. >>>>>> >>>>>> Again, oddly, there is no such prohibition in the language against >>>>>> declaring a formal parameter of empty type. Cm3 prohibits it, >>>>>> and calls it a 'variable' in the error message. >>>>> >>>>> You're right, though it's not the parameter that errors but the variable associated with the parameter. >>>>> >>>>>> Again, language and compiler should agree. >>>>> >>>>> Can you point me to the relevant entries in the language spec? >>>>> >>>>>> >>>>>> The language also prohibits applying FIRST and LAST to the empty >>>>>> enumeration, but they are OK applied to an empty subrange. >>>>>> This makes sense, because they return values of the base type >>>>>> of the argument type, and such values exist for an empty subrange >>>>>> but not the empty enumeration, whose base type is only itself. >>>>>> >>>>>>> >>>>>>> On May 23, 2011, at 8:41 AM, Hendrik Boom wrote: >>>>>>> >>>>>>>> On Sun, May 22, 2011 at 11:18:02PM +0000, Jay K wrote: >>>>>>>>> >>>>>>>>> Well, I can build the whole tree and see how many times it helps. >>>>>>>>> I think this is a pretty standard optimization technique. >>>>>>>>> Though it'd work better with compiler-derived additional information. >>>>>>>>> >>>>>>>>> I initially happened upon this idea developing test cases. >>>>>>>>> >>>>>>>>>> The code assumes the minimum of a type is less than or equal to its maximum. >>>>>>>>> >>>>>>>>> I'll change it not have that problem -- to just fall back to usual pessimistic code for such types, I guess. >>>>>>>> >>>>>>>> What *is* the semantics of a range whose minimum is greater than its >>>>>>>> maximum? There plainly can't be any values in this range. How is a >>>>>>>> variable of this tyoe initialized? Not to some arbitrary value of the >>>>>>>> type, because there aren't any. I can see this type being useful to >>>>>>>> admit convenient generalizations -- for example, an array with n >>>>>>>> elements can still exist if n happens to be zero, but it seems to me >>>>>>>> that any code involving a value of the range for subscripts for this >>>>>>>> array must be simple unexecutable. >>>>>>>> >>>>>>>> Or is there some latitude available in the principle that a value of a >>>>>>>> variable must always be of the correct type? >>>>>>>> >>>>>>>> -- hendrik >>>>>>> >>>>>>> >>>>> >>>>> >>> >>> > > From rodney_bates at lcwb.coop Wed May 25 17:55:11 2011 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Wed, 25 May 2011 10:55:11 -0500 Subject: [M3devel] range analysis? In-Reply-To: <20110524202150.5B4711A2078@async.async.caltech.edu> References: <4DDC11C3.8090303@lcwb.coop> <20110524202150.5B4711A2078@async.async.caltech.edu> Message-ID: <4DDD265F.3020102@lcwb.coop> On 05/24/2011 03:21 PM, Mika Nystrom wrote: > "Rodney M. Bates" writes: > ... >> >> My first thought was that this argument is no more or less applicable to >> a procedure type containing a formal of empty type than to a record >> type containing a field (which is currently defined as a variable) >> of empty type. Both are just types constructed from other type(s), >> to be maybe instantiated later. In the case of the record, we now >> disallow the type to be constructed. Your proposal would inconsistently >> allow the procedure type to be constructed but complain when an >> attempt is made to instantiate it (i.e., call it) later. >> >> My second thought was that a procedure type with empty-typed formal >> is not an empty type, because it contains the perfectly legitimate >> value NIL, which of course, you can't call anyway, thus avoiding the >> issue of instantiating the formal. This is an essential difference >> that would justify doing it differently for records and procedures. >> > > By this logic, shoudln't you also allow such types to be fields > in OBJECT types? Yes. But neither the language nor the compiler allow this. The compiler gives no error on subsequent attempt to allocate such an object, but this is probably just secondary. What about REF RECORD types? REF EmptyType is OK, and the compiler allows it to be defined but not allocated. But the only ways right now to get an empty type are an empty enumeration, empty subrange, or array of empty-typed elements. Try to construct a record with an empty-typed field and the type definition fails. I am doing more compiler experiments and language reading. It looks like we have some inconsistencies. > > Mika > From dabenavidesd at yahoo.es Wed May 25 18:30:51 2011 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Wed, 25 May 2011 17:30:51 +0100 (BST) Subject: [M3devel] range analysis? In-Reply-To: <4DDD265F.3020102@lcwb.coop> Message-ID: <812997.17365.qm@web29709.mail.ird.yahoo.com> Hi all: well that said, please you may take a look at this manual (from p8): http://research.microsoft.com/en-us/um/people/blampson/32a-CedarLang/32a-CedarLangOCR.doc Modula-3 has an action semantics description (not very notorious): http://www.dcs.gla.ac.uk/~daw/publications/M3AS.ps And in the same way: http://research.microsoft.com/en-us/um/people/blampson/48-POCScourse/48-POCS2006.pdf page 24 Thanks in advance, hope it helps a bit --- El mi?, 25/5/11, Rodney M. Bates escribi?: > De: Rodney M. Bates > Asunto: Re: [M3devel] range analysis? > Para: m3devel at elegosoft.com > Fecha: mi?rcoles, 25 de mayo, 2011 10:55 > > > On 05/24/2011 03:21 PM, Mika Nystrom wrote: > > "Rodney M. Bates" writes: > > ... > >> > >> My first thought was that this argument is no more > or less applicable to > >> a procedure type containing a formal of empty type > than to a record > >> type containing a field (which is currently > defined as a variable) > >> of empty type. Both are just types > constructed from other type(s), > >> to be maybe instantiated later. In the case > of the record, we now > >> disallow the type to be constructed. Your > proposal would inconsistently > >> allow the procedure type to be constructed but > complain when an > >> attempt is made to instantiate it (i.e., call it) > later. > >> > >> My second thought was that a procedure type with > empty-typed formal > >> is not an empty type, because it contains the > perfectly legitimate > >> value NIL, which of course, you can't call anyway, > thus avoiding the > >> issue of instantiating the formal. This is > an essential difference > >> that would justify doing it differently for > records and procedures. > >> > > > > By this logic, shoudln't you also allow such types to > be fields > > in OBJECT types? > > Yes. But neither the language nor the compiler allow > this. The > compiler gives no error on subsequent attempt to allocate > such an object, > but this is probably just secondary. > > What about REF RECORD types? > > REF EmptyType is OK, and the compiler allows it to be > defined > but not allocated. But the only ways right now to get > an empty > type are an empty enumeration, empty subrange, or array of > empty-typed elements. Try to construct a record with > an > empty-typed field and the type definition fails. > > I am doing more compiler experiments and language reading. > It looks like we have some inconsistencies. > > > > > Mika > > > From dabenavidesd at yahoo.es Thu May 26 00:38:34 2011 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Wed, 25 May 2011 23:38:34 +0100 (BST) Subject: [M3devel] About modula3.org and modula-3 domain Message-ID: <36867.43808.qm@web29703.mail.ird.yahoo.com> Hi all: has anyone devised an opportunity to have it, or if it is of any help, when would one become important one doesn't know (important for others than us), then if so what do you think and (are you) waiting? :) If any interest in others please if you speak up (e.g .com, et al). Thanks in advance From dabenavidesd at yahoo.es Fri May 27 05:18:16 2011 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Fri, 27 May 2011 04:18:16 +0100 (BST) Subject: [M3devel] About modula3.org and modula-3 domain In-Reply-To: <36867.43808.qm@web29703.mail.ird.yahoo.com> Message-ID: <161903.96505.qm@web29710.mail.ird.yahoo.com> Hi all: and please start to think where we want to go, all your wildest Modula dreams might become true: http://www.ic.unicamp.br/~stolfi/PUB/misc/misc/ramblings/comp/modula/M3-99Wishes.msg http://www.ic.unicamp.br/~stolfi/PUB/misc/misc/ramblings/comp/ReversingGuardedPrograms.mgs http://www.ic.unicamp.br/~stolfi/PUB/misc/misc/ramblings/comp/ReversingGuardedPrograms.mgs Yeah, type inference, plus guarded commands built into language and some Modula-3 Modula type generics type reconstruction before compile time (type checking), and then object generics, who wants to work for (much of this currently solved, who can say about that any other language)? So, maybe its more profitable to start deploying modula4 modula-4 dot com, co, etc at al. I guess you would believe it. PS Finally, all type checking type inferencer and verfication condition generator sound and why not heck complete (so everything is always true it's safe and not UNSAFE) Thanks in advance --- El mi?, 25/5/11, Daniel Alejandro Benavides D. escribi?: > De: Daniel Alejandro Benavides D. > Asunto: [M3devel] About modula3.org and modula-3 domain > Para: m3devel at elegosoft.com > Fecha: mi?rcoles, 25 de mayo, 2011 17:38 > Hi all: > has anyone devised an opportunity to have it, or if it is > of any help, when would one become important one doesn't > know (important for others than us), then if so what do you > think and (are you) waiting? :) > If any interest in others please if you speak up (e.g .com, > et al). > Thanks in advance > From dabenavidesd at yahoo.es Tue May 31 22:12:52 2011 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Tue, 31 May 2011 21:12:52 +0100 (BST) Subject: [M3devel] About modula3.org and modula-3 domain In-Reply-To: <161903.96505.qm@web29710.mail.ird.yahoo.com> Message-ID: <850866.31542.qm@web29713.mail.ird.yahoo.com> Hi all: well, instead of redirection, what about mirroring? We have already a public machine here to do that (first ip #, later another domain I guess or), which ports will we needed to open (does dcvs installation help)? Thanks in advance --- El jue, 26/5/11, Daniel Alejandro Benavides D. escribi?: > De: Daniel Alejandro Benavides D. > Asunto: Re: [M3devel] About modula3.org and modula-3 domain > Para: m3devel at elegosoft.com > Fecha: jueves, 26 de mayo, 2011 22:18 > Hi all: > and please start to think where we want to go, all your > wildest Modula dreams might become true: > http://www.ic.unicamp.br/~stolfi/PUB/misc/misc/ramblings/comp/modula/M3-99Wishes.msg > > http://www.ic.unicamp.br/~stolfi/PUB/misc/misc/ramblings/comp/ReversingGuardedPrograms.mgs > > http://www.ic.unicamp.br/~stolfi/PUB/misc/misc/ramblings/comp/ReversingGuardedPrograms.mgs > > Yeah, type inference, plus guarded commands built into > language and some Modula-3 Modula type generics type > reconstruction before compile time (type checking), and then > object generics, who wants to work for (much of this > currently solved, who can say about that any other > language)? > > So, maybe its more profitable to start deploying modula4 > modula-4 dot com, co, etc at al. I guess you would believe > it. > > PS Finally, all type checking type inferencer and > verfication condition generator sound and why not heck > complete (so everything is always true it's safe and not > UNSAFE) > > Thanks in advance > > --- El mi?, 25/5/11, Daniel Alejandro Benavides D. > escribi?: > > > De: Daniel Alejandro Benavides D. > > Asunto: [M3devel] About modula3.org and modula-3 > domain > > Para: m3devel at elegosoft.com > > Fecha: mi?rcoles, 25 de mayo, 2011 17:38 > > Hi all: > > has anyone devised an opportunity to have it, or if it > is > > of any help, when would one become important one > doesn't > > know (important for others than us), then if so what > do you > > think and (are you) waiting? :) > > If any interest in others please if you speak up (e.g > .com, > > et al). > > Thanks in advance > > >