[perl #22877] GC/Sweep errors in latest build
# New Ticket Created by "Clinton A. Pierce" # Please include the string: [perl #22877] # in the subject line of all future correspondence about this issue. # http://rt.perl.org/rt2/Ticket/Display.html?id=22877 > This bug did not make itself known in a 6/23 checkout, and appeared sometime in the last week (I've only now synched my copy with CVS). I don't have a small test case for this. I apologize. To reproduce the bug: checkout and build latest parrot tree $ cd languages/BASIC/compiler $ cat > test.bas dim a$() for i = 0 to 100 step .5 for j = 1 to 30 a$(j)=" " next j for j = 1 to 30 print " "; next j print i next i ^D $ perl compile.pl test.bas $ ../../imcc/imcc TARG_test.imc And the apparent symptom is the loop counter (i) only goes up to 2 -- it should have gone to 100, by steps of 0.5. If I alter the BASIC program in any way the bug gets delayed a little further or never happens at all. Hacking a "sweepoff" and "collectoff" into the PIR (TARG_test.imc) before anything else happens makes the bug go away. I don't think this is a BASIC bug, nor do I think it's a register allocation/spilling problem in IMCC. Placing traces in the PIR code causes the bug to move around also. Usually only delaying the onset of the bug.
[perl #22854] Incongruity in Parrot IO and/or Parrot I/O crashes on STDIN read
# New Ticket Created by "Clinton A. Pierce" # Please include the string: [perl #22854] # in the subject line of all future correspondence about this issue. # http://rt.perl.org/rt2/Ticket/Display.html?id=22854 > This is either an oversight in the current implementation *or* its a bug. Or both. Bug described is on Win32. To read a line of input: readline Sx, Ix Switches to line buffered mode and reads from fd Ix. This works great: readline $S0, 0 print $S0 But is the old, deprecated way of doing things. As a matter of fact, it's nigh impossible now to open an FD to a file and do anything useful with it as enough bits of the "old way" of doing things are dismantled now... So, I'm trying to use the new ParrotIO stuff, and according to it I should get a ParrotIO object for STDIN: fdopen $P1, 0, "r" And then use the read Sx, Px, Ix function (which on a line-buffered descriptor line STDIN, should stop at EOL): read $S0, $P1, 255 This crashes: .sub _main fdopen $P1, 0, "r" # STDIN read $S0, $P1, 255 print $S0 end .end Suggestions welcome!
Re: [perl #22767] IMCC/Parrot leak and eventual segfault (partially solved)
At 09:22 PM 6/23/2003 +, you wrote: # New Ticket Created by "Clinton A. Pierce" # Please include the string: [perl #22767] # in the subject line of all future correspondence about this issue. # http://rt.perl.org/rt2/Ticket/Display.html?id=22767 > I apologize for the length of this example. I've spent a goodly part of this afternoon trying to track this one down and can't get a handle on a smaller example. Found the bug. Mostly MEA CULPA. A thousand pardons to the good Parrot folk. When calling a sub like this: .arg 0 call _foo It's probably a good thing to take the 0 off the stack at some point. Tends to help with the crashes. That was my bug. Interestingly enough though there still lurks a bug in Parrot somewhere. Here's a much smaller test case: .sub _main $P0=new PerlHash $P0["value"]=0 store_global "PRINTCOL", $P0 USERLABEL_0 .arg 0 call _POSIX_INKEY .arg 1.0 .arg 1 call _BUILTIN_DISPLAY branch USERLABEL_0 end # (unreached) .end .sub _BUILTIN_DISPLAY saveall .param int argc .local int PRINTCOL .param float number find_global $P0, "PRINTCOL" set PRINTCOL, $P0["value"] set $P0["value"], PRINTCOL store_global "PRINTCOL", $P0 restoreall ret .end .sub _POSIX_INKEY saveall $P0=new PerlHash global "fcntl_mode" = $P0 restoreall ret .end This too will segfault after a while. What's going on is the mail loop (USERLABEL_0) calls POSIX_INKEY and an extra INT gets left on the stack. After a while, these build up and something goes haywire and *crunch*. But watch this: .sub _main LOOP: .arg 0 call _foo branch LOOP .end .sub _foo ret .end This suffers from the same logic bug (leaving an extra INT on the stack for each sub call) but *PARROT* *DOESN'T* *CRASH*. Leaks like hell, sure, but no crashes. The something about the find/store global or the new PerlHash in the loop causes the actual crash to happen. [Although a suggestion. After the crash bug gets fixed, a "stack overflow" error or some such nonsense being emitted from the VM might be a good idea. Knowing that: LOOP: push 0 branch LOOP will eventually cause a segfault makes me pine for my 6502 where: LOOPPHA JMP LOOP Would cause the SP to spin like a top all over Page 1. Over and over and over and over... No crash, just infinite fun. When the stack can't grow a nice message would help.]
[perl #22767] IMCC/Parrot leak and eventual segfault
# New Ticket Created by "Clinton A. Pierce" # Please include the string: [perl #22767] # in the subject line of all future correspondence about this issue. # http://rt.perl.org/rt2/Ticket/Display.html?id=22767 > I apologize for the length of this example. I've spent a goodly part of this afternoon trying to track this one down and can't get a handle on a smaller example. Running this on any recent build of Parrot (Win32 or Linux) leaks like a seive and will eventually give a segmentation fault. On my Linux machine it takes 26K repetitions. On my Win32 machine, much fewer. Removing any of the following will cause the segfault to go away: either of the "call _BUILTIN_DISPLAY" statements. the "call _set_nonblock" statement *ALL* of the references to the global PRINTCOL. The i=i+1 logic. ** Using IMCC to produce PASM, and then assembling the PASM works fine! ** [The odd look of this example is because it's a compiled BASIC program. Bits of the runtime are included in here, seriously hacked up for brevity. Whenever I remove these last few pieces, the segfault goes away.] Help! And thanks. .const int TYPE = 0 .const int VALUE = 1 .local string JUMPLABEL .sub _main $P0=new PerlHash $P0["value"]=0 store_global "PRINTCOL", $P0 call _basicmain_run end .end .sub _basicmain .local float i .local string t_string .sub _basicmain_run # Always jump here. call _basicmain_main ret .end .sub _basicmain_main saveall USERLABEL_0: # For user branch (100) # # Evaluating t$ = inkey$ ( ) # Result in t_string of type S .arg 0 # argc call _POSIX_INKEY .result $S0 t_string = $S0 # # Evaluating i = i + 1 # Result in i of type N $N0 = 1.0 + i i = $N0 # # Evaluating i # Result in i of type N .arg i .arg 1 call _BUILTIN_DISPLAY .arg "\n" .arg 1 call _BUILTIN_DISPLAY branch USERLABEL_0 # Goto 100 # # ### # Program Termination # ### restoreall ret # back to _main .end# main segment .end# outer segment .const int FLOAT = 2 .const int STRING = 3 .sub _BUILTIN_DISPLAY # void display(string|float thingy[, string|floa t thingy2]) saveall .param int argc .local string buf .local int intver .local string s .local int PRINTCOL find_global $P0, "PRINTCOL" set PRINTCOL, $P0["value"] set buf, "" NEXT: eq argc, 0, END_DISPLAY dec argc entrytype $I0, 0 eq $I0, STRING, DISPSTRING ne $I0, FLOAT, DISPERR # Now, do floats .param float number set intver, number set $N0, intver eq $N0, number, DISPINT # Nope, it's an integer. # Integers display -1234_ # or _1234 DISPINT:set $S0, intver lt intver, 0, NEGINT concat buf, " " NEGINT: concat buf, $S0 concat buf, " " branch NEXT DISPSTRING: .param string str length $I0, str concat buf, str eq str, "\n", DISPNL add PRINTCOL, PRINTCOL, $I0 branch NEXT DISPNL: set PRINTCOL, 0 branch NEXT END_DISPLAY: print buf set $P0["value"], PRINTCOL store_global "PRINTCOL", $P0 restoreall ret DISPERR:print "Unknown type on stack to print\n" end .end .sub _set_nonblock # void _set_nonblock $P0=new PerlHash #set $P0["value"], I11 store_global "fcntl_mode", $P0 ret .end .sub _POSIX_INKEY saveall call _set_nonblock .return "" # Normally this returns the retrieved keystroke... restoreall ret .end
Re: Portable way of finding libc, unbuffered reads
At 11:55 PM 6/20/2003 +0200, Jens Rieks wrote: > (Which in itself tickles and scares the bejesus out of me.) Is there a > good way of finding the standard C library on a Unix system other than > hard-wiring it in like this? Yes. Parrot is linked with the standard C library. You can get a handle for the own executable by passing a NULL pointer to dlopen. You can also use this handle to call libc functions. You can not pass a NULL pointer to loadlib at the moment, this small hacks "converts" an empty string to a NULL pointer to pass it to Parror_dlopen: const char * s = 0; if( $2->strlen != 0 ) { s = string_to_cstring(interpreter, ($2)); } p = Parrot_dlopen(s); With this hack, the following code will work: loadlib P1, "" dlfunc P0, P1, "system", "it" set I0, 1 set S5, "ls" invoke end A very cool hack, indeed. :) It's gonna need a little work though. On Win32 Parrot_dlopen is a passthrough to LoadLibrary() which, as far as I can tell, doesn't have the same behavior for this case. *But* it seems as though if you can find parrot's name (imcc.exe, parrot.exe, etc...) and pass *that* to loadlib it should work fine. Maybe. More testing required. On my linux box (which was the issue...) it seems fine though. Whee. Thanks!
[perl #22718] core function index() returns -1 when search string contains spaces
# New Ticket Created by "Clinton A. Pierce" # Please include the string: [perl #22718] # in the subject line of all future correspondence about this issue. # http://rt.perl.org/rt2/Ticket/Display.html?id=22718 > In this code: .sub _main .local string source .local string lookfor source="This is not quite right" lookfor=" is " index $I0, source, lookfor, 0 print "(expect 4) $I0 = " print $I0 # you'll actually get -1 lookfor="is" index $I0, source, lookfor, 0 print "\n(expect 2) $I0 = " print $I0 # You will correctly get 2 end .end The string " is " (note the spaces) will not be found within "This is not quite right". Removing the spaces has the expected results. I looked briefly for an explanation in strings.c but my eyes glazed over at the sight of the multibyte and encoding stuff.
Portable way of finding libc, unbuffered reads
The following code works just fine: loadlib P1, "/lib/libc.so.6" dlfunc P0, P1, "system", "it" set I0, 1 set S5, "ls" invoke end (Which in itself tickles and scares the bejesus out of me.) Is there a good way of finding the standard C library on a Unix system other than hard-wiring it in like this? Also, is there any way yet of getting an unbuffered read (in parrot) so I can getc() from the keyboard? I should ask, is there an *approved* way of doing that now? I'm fairly familiar with C's I/O model so I could pull it off with ioctl(), fcntl(), etc... and all of their friends, but alas they're not around yet. These questions are not necessarily related. Or unrelated. :)
PerlHash keys
Any thought on when PerlHashes will be able to allow us to iterate over the keys? Possibly do things like: new P0, .PerlHash set P0["skeleton"], value set P0["master"], value set P0["Odin'sBro"], value set P0["USPO4,314,236"], value set P0["burro"], value new P1, .PerlArray set P1, P0 # P1=keys(P0) ? Or plans for some kind of iterator PMC? new P1, .PerlHashIterator set P1, P0 # Bind P1 to P0, above new P2, .PerlArray set P2, P1 # P2=keys(P0) set P1, 0 # Reset to 0 set S0, P1 # $_ = (keys(P0))[0] set S0, P1 # $_ = (keys(P0))[1] # etc... set I0, P1 # $_ = scalar keys P0, or set I0, P0 set S0, P1[4] # No perl equivalent... set P1[4], "Foo" # No perl equivalent... like $_=$h{$a}; delete $h{$a}; $h{$b]=$_; Are there places in the code/docs I could poke around in with a sharp stick for enlightenment on what's going to happen?
[perl #22706] IMCC (& Parrot) crash with -t when invoke is run
# New Ticket Created by "Clinton A. Pierce" # Please include the string: [perl #22706] # in the subject line of all future correspondence about this issue. # http://rt.perl.org/rt2/Ticket/Display.html?id=22706 > Running imcc -t or parrot -t over an invoke instruction causes the programs to segfault. This happens under Win32. I do not have a platform independant example. .sub _win32_setup # void win32_setup(void) saveall loadlib P1, "kernel32.dll" dlfunc P0, P1, "GetStdHandle", "pi" set I0, 1 set I5, -11 invoke # Will crash here. store_global "kernel32", P1 store_global "Win32handle", P5 restoreall ret .end
Something to pass the time.
If you want something to play with, update the languages/BASIC/compiler tree and run the chess program. perl compile.pl samples\chess.bas ..\..\imcc\imcc.exe TARG_test.imc (modify for your path delimiters, executable extensions, etc... use a recent version of imcc too) I spent the last three weeks re-writing BASIC to emit IMCC and to do more at compile-time, less at runtime. It's *very* quick after I took Leo's hints on how to structure my IMC properly, running at about 1/4 the speed of the same code under Microsoft's QuickBASIC. (I still need to finish BASIC's I/O and structures...) This version runs colorfully under Win32 consoles and Linux using a good ANSI Terminal. I've had reports that the ANSI stuff works fine under OSX's Terminal App and cygwin/Win32 so this should look just peachy everywhere. Instructions on gameplay are onscreen. The chess logic was written long, long ago by Dieter Steinwender (editor for Computer-Schach and Spiele) for "didactic purposes". I think it was originally to solve Checkmate-in-X-Moves problems. I've received modification and redistribution permission from him under Parrot's terms for this purpose. The game is *very* deterministic and doesn't recognize a draw, therefore autoplay mode will only perform 20 moves at a time. Enjoy. :)
[perl #22645] IMCC Nested .subs cause segfaults
# New Ticket Created by "Clinton A. Pierce" # Please include the string: [perl #22645] # in the subject line of all future correspondence about this issue. # http://rt.perl.org/rt2/Ticket/Display.html?id=22645 > I'm exploring IMCC's ability to have nested subs. The following code: .sub _main .sub dummy call inner1 call inner2 end .end .sub inner1 print "Inner1\n" ret .end .sub inner2 print "Inner2\n" ret .end end # safety? .end end # safety? Causes IMCC to segfault. Asking IMCC to generate pasm produces reasonable code: dummy: bsr inner1 bsr inner2 end inner1: print "Inner1\n" ret inner2: print "Inner2\n" ret _main: end end
How do I write a language debugger?
(This is mostly a platform-specific question, as I've written a few and just need to know what I'm doing wrong.) The design for BASIC's debugger I've got now resembles this: .sub _main .local foo .local bar [...rest of declarations...] [PIR for statement 1...] bsr DEBUGGER [PIR for statement 2...] bsr DEBUGGER [PIR for statement 3...] bsr DEBUGGER end # This block appears at the end of every BASIC lexical scope. DEBUGGER: if one-stepping, DEBUG # Loop over break list if current statement is on global break list, DEBUG # End loop ret DEBUG: # Push lexically scoped things into a Px register # so I can see them (by name) outside of this scope $P0=new PerlHash $P0["foo"]=foo $P0["bar"]=bar # etc... .arg $P0 call _DEBUG_CMDS .result $P0 # Put variable values back into lexicals foo=$P0["foo"] bar=$P0["bar"] ret .end .sub _DEBUG_CMDS .param PerlHash values # Debugger command-line interface...etc... .return values .end And this seems to work. Everywhere that I've got a lexical scope (most BASIC programs only have one, newer ones a couple) I repeat the DEBUGGER and DEBUG labels at the end of the block, of course using whatever variables are declared inside of that block. This functions fine. However... Apparently, skipping forward (bsr) and back (ret) inside of this block is causing IMCC fits -- it'll compile a program like this, but it will take a very long time. I'm looking for suggestions on how I could improve this. Right now it's simple, and it works. When the blocks get too large though it's horribly inefficient at compile-time.
[perl #22617] IMCC duplicate labels in different subs cause wrong branch
# New Ticket Created by "Clinton A. Pierce" # Please include the string: [perl #22617] # in the subject line of all future correspondence about this issue. # http://rt.perl.org/rt2/Ticket/Display.html?id=22617 > The following code: .sub _realmain bsr FOO call _function end FOO:print "In main's FOO" ret .end .sub _function bsr FOO ret FOO:print "in the function's FOO" ret .end Causes "In main's FOO" to be printed twice. While an understandable behavior, probably not the correct one. Language in parsing.pod indicates that perhaps the labels should be munged by IMCC. If this *is* the correct behavior, then a "duplicate label" error of some kind should be emitted by IMCC.
[perl #22521] IMCC causes seegfault with many perlarrays and perlhashes
# New Ticket Created by "Clinton A. Pierce" # Please include the string: [perl #22521] # in the subject line of all future correspondence about this issue. # http://rt.perl.org/rt2/Ticket/Display.html?id=22521 > I'm not sure what triggers this bug, but I can reliably reproduce it. The code is *far* too large to list here, but this perl script will generate the appropriate code in larger and larger samples until it starts crashing. Adjust as appropriate: for($s=10; $s<1; $s+=100) { print "Number: $s\n"; open(IMCC, ">foo.imc") || die; print IMCC <
flushing STDOUT before reading STDIN
A small annoyance, I can't seem to write a good line-input routine as of very recent changes (synced yesterday, noon). All I'm trying to do is variations on: print "? " readline S0, 0 And no prompt shows before the readline starts its business. Any suggestions as to how I can flush stdout before beginning input and whatnot? I'm not above resorting to PASM hackery at this point, since the I/O is in flux.
Re: Register allocation bug in IMCC? Or misunderstanding on my part?
At 11:10 PM 6/1/2003 -0400, Uri Guttman wrote: why don't you manage your own basic call stack in an array or PerlArray or something? trying to map that mess of call/return poo onto a proper compiler with register allocation is going to lose us the services of leo while he recuperates at the hospital for homicidal BASIC coders. Naw. I'm not homocidal. Suicidal with a masochistic bent, that's all. And I don't think I've ever asked for anything from the Parrot team other than opinions on honest-to-goodness bugs or understanding of some area of how to target this platform. Hope no-one's going to need a pshrink after this. I only ask odd questions because sometimes I'm dealing with odd things. Like programs that are essentially one big compilation unit -- almost, and doing odd things with bsr/ret... you will just have to bite the bullet and emulate your own virtual engine over parrot and not try to map BASIC directly to it. so code a VM with BASIC flow control. you can probably do something odd like make each BASIC statement into a parrot sub. then just compile your basic into a simple flow control IL that just calls parrot subs. the subs all have access to your need globals (with the obvious find_global/set_global :) a primary global now is the BASIC VM PC. As far as I know, BASIC only gets weird with flow control in two places. One is 'RETURN X', another is computed goto 'goto X'. The former I'm handling be wrapping bsr/ret with a little bit of code (after each bsr, the code asks "was the ret destined for me or not?"). The latter is handled by a table inserted into the code mapping the compile-time labels over to runtime destinations. So that: branch USERLABEL_100# Normal goto USERLABEL_100: # Expression, etc... result in $S0 branch COMPUTED_GOTO COMPUTED_GOTO: eq $S0, "USERLABEL_10", USERLABEL_10 eq $S0, "USERLABEL_20", USERLABEL_20 etc... print "Label " print $S0 print " does not exist at line " print BASICLINE end And the COMPUTED_GOTO jumptable gets inserted in the code only if the program does something stupid like a computed goto. BASIC compilers/interpreters have always felt free to punish the programmer with space/speed tradeoffs for programmer laziness. feel free to tell me this is total cocky-pop. :) In the first incarnation (04/2002) the Parrot VM (pre-PerlHashes mind you) was an inconvenience and BASIC essentially was inside it's own little VM on top of this odd processor. I'd like to exercise as many the facilities available to me now for speed and whatnot. This re-targeting from PASM to PIR is much easier than the original PASM port to begin with.
Re: Register allocation bug in IMCC? Or misunderstanding on my part?
At 10:29 PM 6/1/2003 +0200, Leopold Toetsch wrote: eq RETURNTO, "10", CONT_10 AFAIK are these "line numbers", why do you want to use strings - but I really don't know (and will for sure not learn) this "language". Because "line numbers" are Ancient Basic for designating branch destinations in programs (and statement order!). Nowadays they're optional. They're strings because instead of line numbers, labels can be used. So a perfectly valid BASIC program can even mix forms. 10 print "Hello world" 20 gosub mysub 30 end mysub: print "Goodbye, world" return Yes, my friend. Continue to use quotes around the word "language" when describing this mess. Without RETURN x, just plain old GOSUB/RETURN I could let PIR/PASM handle all by itself with no supervision. Or you handle "normal subs" like that and generate special code for "return x"? I could, except that it's impossible to tell where exactly the exit point of a "subroutine" (for GOSUB) is in a BASIC program. In fact, all "GOSUB" destinations could use an unconditional branch to all use a common RETURN point. You just return when you stumble across a return. Further analysis of where the "subroutines" are may be impossible with mechanical (or human) analysis at compile time: 5 rem Valid but seriously spaghettified BASIC example. 7 rem Good luck analyzing this at compile time for entry 9 rem and exit points for the "subroutines". 10 print "Hello, world!" 20 for i = 1 to 3 30 gosub 70 40 next 50 end 70 gosub mysub 80 gosub 110 90 return 100 return 30 110 rem alternate entry point mysub: print "Hello, galaxy!" on int(rnd(2)+1) goto 90, 100 For this, the "Hello, galaxy" subroutine could be entered at two different points (110, "mysub") and exited at one of two randomly chosen points (90 or 100) at runtime. Furthermore, one of the return points (100) changes the exit point of the subroutine entered at line 70 (either 90 or 100). Remember, this is the language that inspired Dijkstra to write "Go To Statement Considered Harmful" (http://www.acm.org/classics/oct95/). :)
Re: Register allocation bug in IMCC? Or misunderstanding on my part?
At 12:00 PM 6/1/2003 -0600, Luke Palmer wrote: If you use them often... then maybe one or two need a real register, but I'd still be weary of doing that. Use find_global and its friends. Eureka! Oh, find_global/set_global, where have you been all my life? Thank you for pointing out the obvious. :) > * Examples of things that are really global in a BASIC machine: current > random number seed, cursor column position, console current character > attributes, last value picked up from a READ/DATA combo (line & position), > structure definition table, and a GOSUB call-stack lookback specifically > for "RETURN x". Yeah, most of those seem like they can be stored in the global name table instead of a register. Load them in when you need them. Except the latter, which seems like you should be using the call stack, if I'm not misunderstanding. I thought so too, but no sane language I know would allow this kind of nonsense: 10 GOSUB 100 20 PRINT "I get printed too." 50 REM And the stack is empty at this point. 90 END 100 GOSUB 200 110 PRINT "Nope, won't see me" 199 RETURN 200 GOSUB 1000 210 PRINT "Nope, won't see me either." 299 RETURN 1000 PRINT "You *will* see me" 1010 RETURN 10 I think in PASM this would be something like bsr USERLABEL_100 eq RETURNTO, "10", CONT_10 eq RETURNTO, "", CONT_10 ret CONT_10: print "I get printed too" end USERLABEL_100: bsr USERLABEL_200 eq RETURNTO, "100", CONT_100 eq RETURNTO, "", CONT_100 ret CONT_100: print "Nope, won't see me" set RETURNTO, "" ret USERLABEL_200: bsr USERLABEL_1000 eq RETURNTO, "200", CONT_200 eq RETURNTO, "", CONT_200 ret CONT_200: print "Nope, won't see me either." set RETURNTO, "" ret USERLABEL_1000: print "You *will* see me" set RETURNTO, "10" ret Of course, this allows for jumping into this GOSUB/RETURN nonsense anywhere in the mix and still a RETURN x takes you back to the right place. Oh and worse? RETURN x can take a variable in some cases. (Literally, x=10, return x) Without RETURN x, just plain old GOSUB/RETURN I could let PIR/PASM handle all by itself with no supervision.
Re: Register allocation bug in IMCC? Or misunderstanding on my part?
At 06:57 PM 6/1/2003 +0200, Leopold Toetsch wrote: Clinton A. Pierce <[EMAIL PROTECTED]> wrote: > The following code: > push_integer() not implemented in class 'PerlHash' > This is, as far as I can tell, because the same register is used by IMCC > for both the READDATA and RESTOREINFO locals, thus by the time that the sub > _data gets around to being run, READDATA has become a PerlHash (imcc -t): >>PC=0; OP=821 (new_p_ic); ARGS=(P0, 14) >>PC=3; OP=821 (new_p_ic); ARGS=(P0, 15) Yep. Good analysis. You could tell it a bug. Imcc should follow the code path into the subroutine. But he problem is: the subroutine isn't known, when _main is compiled. So IMCC only sees one usage of the Array and one usage of the Hash amd assigns both to the same register P0. Makes sense. If you want really use such constructs, you can't put them in different compilation units, because they are basically one unit. So a BASIC IMCC program, with all of the builtin functions it needs, plus the actual user program itself as one compilation unit? All for the sake of a few needed globals? Sounds ghastly. Much better is to implement some kind of calling conventions. Except that these represent true global data structures that the entire BASIC machine needs. They're not really things to be passed around from place to place and the thought of having a Px register to hold the "state of BASIC" and passing it (potentially) everywhere seems kinda silly for a language that isn't really threaded in any incarnation and is ever only going to need one state. I've *got* good, sound calling conventions now but there are things (sofar, only half a dozen*) that exist in an outermost scope that need initialization. I could turn the whole thing upside-down (subs first, main last) except that I'd need a token outer main() to call the initialization routine. And from a quick test IMCC can tell that the execution path jumped down, and optimizes those registers away anyway. Nevermind. Further suggestions, given better info? * Examples of things that are really global in a BASIC machine: current random number seed, cursor column position, console current character attributes, last value picked up from a READ/DATA combo (line & position), structure definition table, and a GOSUB call-stack lookback specifically for "RETURN x".
Register allocation bug in IMCC? Or misunderstanding on my part?
The following code: .local PerlArray READDATA .local PerlHash RESTOREINFO .sub _main READDATA = new PerlArray RESTOREINFO = new PerlHash call _data end .end .sub _data push READDATA, 10 ret .end Throws an error in the VM of: push_integer() not implemented in class 'PerlHash' This is, as far as I can tell, because the same register is used by IMCC for both the READDATA and RESTOREINFO locals, thus by the time that the sub _data gets around to being run, READDATA has become a PerlHash (imcc -t): PC=0; OP=821 (new_p_ic); ARGS=(P0, 14) PC=3; OP=821 (new_p_ic); ARGS=(P0, 15) PC=6; OP=752 (bsr_ic); ARGS=(2) PC=8; OP=722 (push_p_ic); ARGS=(P0, 10) push_integer() not implemented in class 'PerlHash' This seems to conflict with the example that Leo gave me on the 28th. I'm not sure if this is a bug or if I've got some whacky misunderstanding of how things work. I think my intention is clear by the above piece of code. Suggestions? As a postscript, changing the code to: .local PerlArray READDATA .local PerlHash RESTOREINFO .sub _main READDATA = new PerlArray RESTOREINFO = new PerlHash push READDATA, 10 end .end Produces the desired (and expected) output. READDATA and RESTOREINFO each get their own register: PC=0; OP=821 (new_p_ic); ARGS=(P0, 14) PC=3; OP=821 (new_p_ic); ARGS=(P1, 15) PC=6; OP=722 (push_p_ic); ARGS=(P0, 10) PC=9; OP=0 (end) This was all done with imcc, cvs updated as of 12:00 Eastern time. No optimization options selected.
[perl #22360] IMCC error for unexpected X, expecting Y needs more information
# New Ticket Created by "Clinton A. Pierce" # Please include the string: [perl #22360] # in the subject line of all future correspondence about this issue. # http://rt.perl.org/rt2/Ticket/Display.html?id=22360 > (Low priority, more an annoyance than anything.) When the message of the form: parse error, unexpected FOO, expecting BAR is produced such as: C:\projects\perl\parrot\languages\BASIC\compiler>..\..\imcc\imcc err.imc (error) line 8: parse error, unexpected IDENTIFIER, expecting '\n' Didn't create output asm. IMCC should identify the file that the error occurs in, as well as what the IDENTIFIER was that caused the error message in the first place. For example, for included.imc brought in from main.imc: .sub foo: # void foo(int argc[, string arg) # Stuff in here .end Should probably say something to the effect of: (error) line 1, included.imc: parse error, unexpected LABEL ("foo:"), expecting IDENTIFIER Didn't create output asm.
[perl #22359] IMCC Optimizer fails with various types of hand-rolled loops
# New Ticket Created by "Clinton A. Pierce" # Please include the string: [perl #22359] # in the subject line of all future correspondence about this issue. # http://rt.perl.org/rt2/Ticket/Display.html?id=22359 > The IMCC optimizer run with these options: ..\..\imcc\imcc -Op1 -d60 err.imc Bug #1: Issues the error message (now a warning, but probably a problem nontheless): error:imcc:sort_loops: loop 1 contains first but notlast of outer loop 0 A sample to cause this problem is: .sub _main .local int count set count, 2 KEYLOOP:le count, 0, BAIL eq count, 2, TWO eq count, 1, ONE end TWO:dec count branch KEYLOOP ONE:dec count branch KEYLOOP BAIL: print "Hello" end .end Bug #2 Run with the same options, and slightly simplified code, this error message is emitted: if_branch eq ... ONE error:imcc:iANY file err.imc line 12: op not found 'ne_i_ic' (ne<3>) A sample to cause this problem is: .sub _main .local int count set count, 1 KEYLOOP:le count, 0, BAIL eq count, 1, ONE end ONE:dec count branch KEYLOOP BAIL: print "Hello" end .end Running either sample without the optimizer produces the expected results.
Re: IMCC, PASM and constants/macros
At 11:13 AM 5/28/2003 -0400, Clinton A. Pierce wrote: # These are vastly simplified, but give you the idea And of course, by "vastly simplified" I meant "completely wrong" because the sample shown won't work because of the saveall and restoreall before and after the array creation in _DIMENSION. But you still get the idea. :)
Re: IMCC, PASM and constants/macros
At 05:45 PM 5/27/2003 -0400, you wrote: On Tue, 2003-05-27 at 08:01, Clinton A. Pierce wrote: > At 11:57 PM 5/26/2003 -0400, Will Coleda wrote: > >Perhaps "macros only work in assembler mode" is the issue? > > > >http://www.mail-archive.com/[EMAIL PROTECTED]/msg14107.html > > > >Regards. > > It was, but I was looking for the "why" of it. Leo answered that ("IMCC > has .const") so I'm all set now. Is there is reason not to s/\.constant/.const/g for consistency's sake? And actually, on further consideration, .const isn't what I want either. What I really want is a #define directive for general-purpose (simple) compile-time substitutions. For example, to refer to a Px register that I'm going to need on-and-off through a program's life to manage BASIC's internal stuff. # These are vastly simplified, but give you the idea .define BASICARR $P .sub _DIMENSION # void DIMENSION(string array) saveall .param string array new $P0, .PerlArray BASICARR[array] = $P0 restoreall .end .sub _ARR_LOOKUP# string ARR_LOOKUP(string key) saveall .param string key set $S0, BASICARR[key] .return $S0 restoreall .end
Re: [perl #21729] IMCC doesn't handle scientific notation constants
At 03:43 PM 3/28/2003 -0500, Joseph F. Ryan wrote: >Example: > > set I0, 1e20 > end > >Results in: > > (error) line 2: parse error, unexpected IDENTIFIER, expecting >'\n' > Didn't create output asm. > Should it, though? Although it would be pretty convienient, I think that handling scientific notation would be an unnecessary complication for IMCC, and it would be better handled by the compilers that target it. (As in, the compiler converts scientific notation to decimal form during compilition to IMCC code.) Not my call. The current assembler does the Right Thing WRT this notation and I'd want numeric constants handled somewhere. :)
[perl #21729] IMCC doesn't handle scientific notation constants
# New Ticket Created by "Clinton A. Pierce" # Please include the string: [perl #21729] # in the subject line of all future correspondence about this issue. # http://rt.perl.org/rt2/Ticket/Display.html?id=21729 > Example: set I0, 1e20 end Results in: (error) line 2: parse error, unexpected IDENTIFIER, expecting '\n' Didn't create output asm. A larger example is BASIC's Connect-4 game: c:> cd parrot\languages\basic\compiler c:> compile.pl samples\conn4.bas c:> ..\..\..\languages\imcc\imcc.exe TARG_test.pasm Results in: (error) line 4329: parse error, unexpected IDENTIFIER, expecting '\n' Didn't create output asm.
Re: IMCC Changes necessary for Win32 builds, imcc links!
[I will confess, I don't entirely understand Microsoft's linker and DLL business. Don't really want to...] Parrot - libparrot.lib gets built as some kind of perverted stub of a library using the "nmake shared" target for parrot. If instead I build libparrot with: lib -out:blib\lib\libparrot.lib [objects..] I get a 5MB libparrot.lib chock full of symbols and other nonsense I need later. IMCC - The target for Win32 needs to be "imcc.exe", not "imcc". Now that I have a working IMCC I should consider how to make a binary Win32 bundle. Suggestions on what needs to be included? Should I just strip out *.[dll,obj,lib] and distribute that? Considering that this really isn't a consumer-ready type of application should the source, docs, intermediate files, etc.. be in the bundle?
IMCC Changes necessary for Win32 builds
Many of these seem to be from "generated" files, so I'd rather let a proper, knowledgable maintainer take care of these. They are: s/CONST/CONSTX/ anywhere in the parser & lexer. Keeps Win32 headers happy as previously mentioned. Index: imcparser.h === RCS file: /cvs/public/parrot/languages/imcc/imcparser.h,v retrieving revision 1.28 diff -r1.28 imcparser.h 51c51 < CONST = 274, --- > CONSTX = 274, 113c113 < #define CONST 274 --- > #define CONSTX 274 Index: imcparser.c === RCS file: /cvs/public/parrot/languages/imcc/imcparser.c,v retrieving revision 1.38 diff -r1.38 imcparser.c 69c69 < CONST = 274, --- > CONSTX = 274, 131c131 < #define CONST 274 --- > #define CONSTX 274 876c876 < "ENDNAMESPACE", "CLASS", "ENDCLASS", "SYM", "LOCAL", "CONST", "PARAM", --- > "ENDNAMESPACE", "CLASS", "ENDCLASS", "SYM", "LOCAL", "CONSTX", "PARAM", Index: imclexer.c === RCS file: /cvs/public/parrot/languages/imcc/imclexer.c,v retrieving revision 1.32 diff -r1.32 imclexer.c 1055c1055 < return(CONST); --- > return(CONSTX); The one "C" language problem: Index: imc.c === RCS file: /cvs/public/parrot/languages/imcc/imc.c,v retrieving revision 1.45 diff -r1.45 imc.c 431a432 > 1; MS's nmake isn't happy with the makefile at all. First: C:\projects\perl\parrot\languages\imcc>nmake Microsoft (R) Program Maintenance Utility Version 7.00.9466 Copyright (C) Microsoft Corporation. All rights reserved. NMAKE : fatal error U1073: don't know how to make 'FORCE' Stop. Removing the .FORCE references gets me something that builds objects. Once the objects are built though, it goes a little nuts trying to do the link. Hundreds of : Microsoft (R) Program Maintenance Utility Version 7.00.9466 Copyright (C) Microsoft Corporation. All rights reserved. cd ../.. && nmake followed by hundreds of: NMAKE : fatal error U1077: 'cd' : return code '0x2' Stop. I suspect something's trying to make one of the OFILES at the bottom, which should already be in there (I removed the OFILES dependancy from imcc temporarily). I'm not really sure what it's trying to do. Further corrections (this is currently empty, and shouldn't be): PARROTLIB = blib/lib/libparrot.lib And manually building with "nmake shared" at the parrot level satisfy this requirement. Then I'm down to link errors at the end of the imcc linking: Microsoft (R) Program Maintenance Utility Version 7.00.9466 Copyright (C) Microsoft Corporation. All rights reserved. link -out:imcc -nologo -nodefaultlib -release-machine:x86 imcparser.obj imclexer.obj imc.obj stacks.obj symreg.obj instructions.obj cfg.obj sets.obj debug.obj optimizer.obj pbc.o bj main.obj parser_util.obj jit.obj ../../blib/lib/libparrot.lib oldnames.lib kernel32.lib user 32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib netap i32.lib uuid.lib wsock32.lib mpr.lib winmm.lib version.lib odbc32.lib odbccp32.lib msvcrt.lib imclexer.obj : error LNK2019: unresolved external symbol _mem_sys_allocate_zeroed referenced in function _new_frame pbc.obj : error LNK2019: unresolved external symbol _mem_sys_allocate_zeroed referenced in funct ion _store_str_const imclexer.obj : error LNK2019: unresolved external symbol _mem_sys_free referenced in function _d estroy_frame optimizer.obj : error LNK2019: unresolved external symbol _mem_sys_free referenced in function _ subst_constants pbc.obj : error LNK2001: unresolved external symbol _mem_sys_free main.obj : error LNK2001: unresolved external symbol _mem_sys_allocate imclexer.obj : error LNK2019: unresolved external symbol _mem_sys_allocate referenced in functio n _yylex instructions.obj : error LNK2001: unresolved external symbol _mem_sys_allocate optimizer.obj : error LNK2019: unresolved external symbol _mem_sys_allocate referenced in functi on _unused_label pbc.obj : error LNK2001: unresolved external symbol _mem_sys_allocate pbc.obj : error LNK2019: unresolved external symbol _Parrot_on_exit referenced in function _e_pb c_open pbc.obj : error LNK2019: unresolved external symbol _PackFile_Segment_new_seg referenced in func tion _make_jit_info pbc.obj : error LNK2019: unresolved external symbol _PackFile_FixupTable_new_entry_t0 referenced in function _store_labels pbc.obj : error LNK2019: unresolved external symbol _string_make referenced in function _add_con st_str parser_util.obj : error LNK2001: unresolved external symbol _string_make pbc.obj : error LNK2019: unresolved external symbol _PDB_extend_const_table referenced in functi on _add_const_str pbc.obj : error LNK2019: unresolved external symbol _PackFile_Constant_unpack_key referenced in
Re: BASIC, IMCC, and Windows.
At 04:53 PM 3/20/2003 +0100, Leopold Toetsch wrote: Clinton A. Pierce wrote: The suggestion was made last week that I try filtering the compiled BASIC stuff through IMCC for performance reasons and whatnot. IMCC seems to want headers that MSVC++ isn't happy with: cl -nologo -O1 -MD -DNDEBUG -DWIN32 -D_CONSOLE -DNO_STRICT -I../../include -Feim cparser.obj -c imcparser.c imcparser.c C:\Program Files\Microsoft Visual Studio .NET\Vc7\PlatformSDK\Include\WinDef.h(159) : error C2059: syntax error : 'constant' Can you have a look at the stated line, maybe its some kind of a name clash. Would also be nice for giure out, by which file WinDef.h got pulled in. It's because in imcparser.c the token CONST is used. In the standard Windows stuff, const is defined as #define CONST const Which of course is a keyword and used everywhere in Win32 header files like: typedef CONST WTHINGY *FOO, *BAR... Changing this to CONSTX in imcparser.c (or any other token) seems to be okay. I don't have the necessary tools to fix this directly (bison, etc..). Also in imc.c ~431: done: } Makes MSVC unhappy. Changing this to: done: 1; } Makes everything all right so far, but I still don't quite have a working imcc. Still slugging through all of this.
BASIC, IMCC, and Windows.
The suggestion was made last week that I try filtering the compiled BASIC stuff through IMCC for performance reasons and whatnot. The suggestion was also made (by me!) that I could produce a "milestone" binary for Windows for distribution. Well, my first attempt at all of the above didn't go well. I can't quite fathom how I'm supposed to build IMCC in a Win32 environment without mixing/matching cygwin and MSVC. Parrot builds fine and by-the-book (perl Configure.pl, nmake, nmake test, etc...) and runs against the Activestate Perl distribution just peachy. IMCC seems to want headers that MSVC++ isn't happy with: cl -nologo -O1 -MD -DNDEBUG -DWIN32 -D_CONSOLE -DNO_STRICT -I../../include -Feim cparser.obj -c imcparser.c imcparser.c C:\Program Files\Microsoft Visual Studio .NET\Vc7\PlatformSDK\Include\WinDef.h(159) : error C2059: syntax error : 'constant' C:\Program Files\Microsoft Visual Studio .NET\Vc7\PlatformSDK\Include\WinNT.h(257) : error C 2059: syntax error : 'constant' C:\Program Files\Microsoft Visual Studio .NET\Vc7\PlatformSDK\Include\WinNT.h(262) : error C 2059: syntax error : 'constant' [...hundreds of errors later...] And it also seems to want (by reading the makefile) bison and flex, neither of which is available in the MSVC Win32 compilation environment. Should I mix and match at least those two components (flex/bison)? Has anyone built IMCC for Win32 before?
Re: Parrot for windows?
At 02:36 PM 3/14/2003 -1000, Joshua Hoblitt wrote: On Fri, 14 Mar 2003, Dan Sugalski wrote: > At 6:59 PM -0800 3/13/03, Robert Spier wrote: > > > If we can't find anothr home for it, I can make a spot on > >> ftp.sidhe.org for it. Not a *fast* home, since it's either 128k or > >> 192k upstream (depending on which interface is active, don't ask) but > >> it will work. I would be more then happy to host binaries on my CPAN mirror (DS3 commodity, OC3 Internet2). > >Maybe when 0.10 is released, Clinton will do another windows build and > >we can put some binaries on www.parrotcode.org? > > That would be really cool. > > What I'd love would be if we could manage an automated build farm, > maybe something linked into the tinderbox builds, that uploaded built > parrots for the different platforms. Just a 'make distclean' then tarball it? Or a new binary only + install framework (make binpkg???) ? > Maybe next week. Maybe not. :) I'd be happy to make up an occasional milestone binary, if there's a standard way it should be put together (i.e. make foo) then lemme know.
Re: Parrot for windows?
At 01:04 AM 3/11/2003 -0500, Benjamin Goldberg wrote: Does anyone have a precompiled parrot binary for Win32, on an ftp or web site somewhere? I'm practicing writing parrot assembler, and I'd like to be able to test my evil creations on my own machine, without having to go through the rigmarole of uploading my file to my sourceforge account, then sshing in to run the scripts. (Plus, the long-term quota on my account is too small to keep around a parrot binary there full time, so I have to re-download and re-compile it when I want to use it, and erase it when I'm done. Bleh!) I've put a copy at http://geeksalad.org/tmp/parrot.zip *temporarily* if you want to grab it. It's compiled with MS Visual .NET using AS Perl 5.6.1 build 633 as its configuration base. It's the whole thing (source, object, docs) from a CVS update about two days ago. It's also pretty large at about 9.5 MB. I suppose if there isn't a windows binary out there, I could try downloading and installing a C compiler (gcc? djgpp?) and then compiling my own parrot... but I don't want to do that much work! MS VC++ or Visual .NET both work wonderfully. Not exactly free though...
languages\BASIC reorg
I re-organized the languages\BASIC tree into "compiled" and "interpreted" sub-trees. The interpreted tree contains the original pasm-only implementation of GW-BASIC as an interpreted language. The compiled tree contains a Quick-BASIC like compiler and a few sample BASIC programs (connect-4, eliza, wumpus, hanoi, etc..). Parrot's GC and speed are *much* improved since I played with it a few months ago. Hanoi for large numbers of disks no longer leaks, and runs noticably faster. Nice job.
Parrot BASIC 2
I sat around trying to think of a witty, pithy way to make this announcement more surreal or frightening than it really is and failed. So I guess I'll let it stand on it's own. I've just completed a complete re-write of BASIC for Parrot. This time I've used QuickBASIC as a model which means there's all kinds of new features, and it's a much friendlier language to work with. It's not complete, but a few tutorials that I found for QuickBASIC can be completed with this compiler. If you're interested, you can get the bundle at http://geeksalad.org/basic/basic2.zip and eventually I suppose I'll hack it into the languages\basic CVS tree in the Parrot distribution. The compiler itself is rather hideous Perl, but the output and the runtime libraries are all pure PASM. Of interest specifically to p6i: This version *almost* works flawlessly under 0.0.8 from about two weeks ago. There's still some memory issues and large programs (like newtrek.bas) that run long enough will segfault. So right now the RT_initialize.pasm file has "collectoff" and "sweepoff" statements and that seems to avoid the symptom. Enjoy. :) From the README file: -- Parrot BASIC 2.0 What is it? It's an implementation of BASIC in Parrot. Unlike version 1, this is modeled after Microsoft's QuickBASIC version 4.5. A quick list of features: * It's compiled directly to Parrot Assembly (PASM) and not interpreted. * Richer syntax than Parrot BASIC 1.0, which was modeled after GW-BASIC * Much, much faster than Parrot BASIC 1.0 * Support for user-defined types * Support for variable scopes+ (+ QB has bizarre ideas of scope. Caveat Programmer.) I couldn't find a proper book on QuickBASIC, and believe it or not Google wasn't terribly helpful in finding a good manual. I did have a QB.exe and a few help files for information. What's missing? The things that are missing fall into three classes. "Someday I'll do these, there's hooks for it but I need a break now." * Keywords: defint const static ubound * SHARED in DIM statements * Exception handling * The keyword USING * The "* length" modifier for strings * Forward-declarations (DECLARE) are missing. For now, your DIM's and functions must by defined before they're used. * DEF FN. It's a special case of FUNCTION. "These are *hard* and I may not do them, ever" * Keywords: common chain bload bsave cseg "These are nearly impossible given where Parrot is now. maybe when the I/O gets rounded out and some libraries get added. Like graphics, sound, and filesystem access." * Keywords: screen pset preset line circle draw view window pmap color palette paint get put pcopy beep sound locate view width resume pos poke peek rset * Most directory manipulations * Record (binary) I/O And I probably have a whacked idea of I/O in QuickBASIC anyway. What's incomplete? Mostly the File I/O stuff. Surprisingly, basic file I/O is working properly. See test #47. What's a hack? Dirty little secrets of PB2; some good, some bad: * single/double are simply Parrot Nx registers * int/long are simply Parrot Ix registers * Everything is case insensitive. * Arrays are really hashes. Yes, "foo(a$)" is now legal BASIC. I'll sneak a "keys()" function into BASIC eventually... * Other bad syntax is forgiven or Something Interesting happens * The _STARTASM directive lets you put PASM in your BASIC code. (see testsuite.pl for an example) * I couldn't wrap my brain around BASIC's scoping to write the expression evaluator properly. It's a kind of dynamic scoping that hurts my head. So the expression evaluator is a postfix machine. * The DIM statement doesn't really need to indicate any kind of size at all. DIM a$(1) will set aside a$ as any n-dimension array of any size. * The random number generator is *intentionally* seeded with a constant to make testing easier. Use "randomize timer" to mix things up. How do I get going? Quickstart? 1. Edit "testrun.pl" and change the pathname at the beginning of the script to wherever parrot is. 2. Type "compile.pl wumpus2.bas" This produces "TARG_test.pasm" and "TARG_localfuncs.pasm" 3. Type "testrun.pl" and enjoy. eliza2 and wumpus2 are simply ports from the Parrot BASIC 1.0 version. All that had to be done were to add DIM statements and a RANDOMIZE. See the notes below for more examples. Where's the advanced syntax stuff? Once you've fixed "testrun.pl" as noted above, the script "testsuite.pl" will run BASIC through its self-tests. If you look through the script there's examples of almost every kind of syntax that I've got working. What are all of these files? RT_* Runtime Libraries. Things like the expression evaluator and builtin functions (add, sub, mul, sin, cos, etc..) COMP_* The compiler itself. Please, oh please don't look at this Perl code. It's terrib
Parrot Builds broken for Win32?
Grabbing the last few snapshots from dev.perl.org, I can't find one that'll build under Win32. During Configure.PL I get these errors: Determining stack growth direction...'.\test.exe' is not recognized as an internal or extern al command, operable program or batch file. Odd number of elements in hash assignment at config/auto/stackdir.pl line 35. Use of uninitialized value in list assignment at config/auto/stackdir.pl line 35. done. Generating config.h...Use of uninitialized value in substitution iterator at lib/Parrot/Conf igure/Step.pm line 102, line 45. done. The rest of the build proceeded without errors. However, 'nmake test' reports: C:\Perl\bin\perl.exe t/harness --gc-debug --running-make-test t/src/basic.# No tests run! t/src/basic.dubious Test returned status 255 (wstat 65280, 0xff00) DIED. FAILED tests 1-2 Failed 2/2 tests, 0.00% okay t/src/exit..# No tests run! t/src/exit..dubious Test returned status 255 (wstat 65280, 0xff00) DIED. FAILED tests 1-2 Failed 2/2 tests, 0.00% okay t/src/intlist...# No tests run! t/src/intlist...dubious Test returned status 255 (wstat 65280, 0xff00) DIED. FAILED tests 1-4 Failed 4/4 tests, 0.00% okay I'm updating from an older, working version because I suspect that under certain circumstances that PerlHash PMC's can lose keys. (YIKE!) I only have obscenely large test cases however... (3K lines of PASM)
Questions about Px registers and memory usage
I'm in the middle of a rather large project, and stopped to do a memory usage sanity check. To my surprise I found a leak and traced it back to the way I was allocating PerlHashes and whatnot. To boil it down further, look at this PASM: LOOP: new P1, .PerlHash branch LOOP What I'd *expect* is that this would have a steady-state, as each new PerlHash is created it bashes the pointer to the previous PerlHash in P1. The old PerlHash would then get garbage collected and after the second iteration I'd reach a steady-state for memory usage. Kinda like this Perl: LOOP: $t={}; goto LOOP; Only that ain't how it works. What happens is that memory gets chewed up quickly. Do I have the wrong idea of how the Px registers are used to point to things (god, I hope not) or is there some GC that needs to happen that isn't (and I can expect it to vanish eventually)?
Re: strange behaviour of concat operator
At 10:22 PM 10/26/2002 +0530, Gopal V wrote: If memory serves me right, Ramesh Ananthakrishnan wrote: > I have this code > > set S12 "" > set I0 0 > WHILE: > concat S12 "hi" > add I0 1 > lt I0 10 WHILE > print S12 > ret ... > Right version of Parrot, so is this a bug? I get No entries on stack! hihihihihihihihihihi last changelog entry in my built parrot is on 2002-03-19 22:54 .. so I guess it's a bit outdated :-) Actually, that's right. The hi's are correct. The "No entries!" error is because there's a "ret" at the end, and presumably this little segment wasn't called with a "bsr". I took out the ret (don't forget to add an end!) and it ran fine, even without the commas.
Re: Off-list discussions, was Re: imcc hack for perl6 regexes
At 08:07 PM 8/21/2002 +0100, Ximon Eighteen wrote: > You _would_ think so, wouldn't you? :) > Personally I've been a little disappointed > in the involvement(interest) of late. > > -Melvin I wonder how many interested observers of this list there are like myself. I only wish I had the time & experience/skill/knowledge to contribute. Keep up the good work. I'm just an observer for now, but keenly interested. I've got a programming project in the works involving Parrot that brings me one step closer to World Domination. Most of the discussion in p6i goes right over my head, but I'm certainly enjoying the fruits of their labors.
Re: strange behaviour of concat operator
At 08:46 AM 10/26/2002 -0700, Ramesh Ananthakrishnan wrote: I have this code set S12 "" set I0 0 WHILE: concat S12 "hi" add I0 1 lt I0 10 WHILE print S12 ret Well S12 does not Concatenate. I tried it a million other times. If S12 is "" or " " or 0 it does not concatenate but just stores "hi" once. Right version of Parrot, so is this a bug? I hunted round the bugdatabase for some time, but couldn't find stuff about this. Which reminds me. Is there a genral introduction as to how to search for stuff in the Bug Database. And if it isn't a stupid question what's a ticket and how do greenhorns like me make the best use of it. The code seems to be correct and I checked that, so I think it's a bug. If it isn't er really sorry. The example seems to run fine here. When writing PASM, it sometimes helps to have multiple builds of Parrot laying around. The one I'm using is about two weeks old and none of the bugs in it seem critical to what I'm doing. Whereas the CVS sync I did at the beginning of the week was most unpleasant. So after building a new version of Parrot (make clean, re-run configure.pl) be sure to run the tests (make test) before you get comfortable with it. Keep whatever old version around that you're sure works. If the new version seems to be bug-compatable with the old one but adds whatever features you're looking for, keep it. If the newer versions seems broke and *stays* broke for a while, post a bug report to p6i with a brief test.
Two problems groping around in PerlHashes
While working on ...something... I found the need to be able to tell if a key exists in a PerlHash. Here's the kicker, I don't know what kind of data's gonna be there: int, float, PMC, or string. After hunting around in t/perlhash.t I found a few examples of checking for keys that don't exist. They look like: new P1, .PerlHash set P0, P1["not_there"] typeof S1, P0 eq S1, "PerlUndef", NOTTHEREBRANCH Okay this is cool, except it doesn't work if the hash has mixed types in it and the key you're looking for *actually exists*. For this code: new P1, .PerlHash set P1["mykey"], I0 # So it will exist set P0, P1["mykey"] Parrot correctly throws an error: Cannot fetch PMC out of non-PMC key! Correct or not, this is a pain in the butt. There's no way to grope around in a PerlHash unless you already know what keys are there and what type they are. What I think we need is an exists opcode. And looking at classes/perlhash.c it looks like there's a exists function already there. I just can't figure out how to use it in PASM. There appears to be no opcode for it. Is this something of the PMC API we can expose to PASM programmers? Can someone gimme a hint of how to make this a real live opcode? Or, if someone can easily turn this on somehow, I think the best API for something like exists would be: exists Px[key], branch So once I can tell the key is there, that brings up the second problem: what exactly is behind that key? A PMC? A native type? The only thing I can think of that would suffice would be to tinker with typeof to make it able to recognize the PASM native types (N, I, S) and then to make it a keyed op.
Re: [perl #17803] [PATCH] Various tests
At 07:42 PM 10/8/2002 -0700, Steve Fink wrote: >Thanks, applied. > >Who came up with the idea of two-argument ne, anyway? That's kind of >bizarre. I'd much rather have it tested if it exists at all, but it >seems pretty obscure. It's not completely without precedent, on the Z-80: RET CC Return from sub if CC is true But reversing the sense of the test makes it doubly weird. :)
Re: [perl #17562] Segfault in stack handling code running ELIZA
The problem is much smaller than that, actually. 10 LET T$=CHR(65)+CHR(66)+CHR(67) 20 PRINT T$ 30 LET A$=RIGHT(T$, 1) 40 QUIT The problem vanishes if any of the following happen: * T$ is constructed with a string assignment (LET T$="ABC") * The PRINT statement is removed * The LET A$= statement is removed * Parrot is run with a -t Various combinations of these bring it back, and make it vanish again. My bets are that something in P21["T"] gets GC'd too soon. When I go back for it later (to RIGHT it), it's already gone
16 Bit integer math
I have a sudden need to do signed 16-bit integer math in PASM. Any suggestions on where to begin? I'd rather not re-invent this wheel if someone else has a better idea. And if I do, where can I find good tools for it?
Re: chr, ord etc
At 03:01 PM 9/9/2002 -0400, Aaron Sherman wrote: >I'd like to start a dialog And since this thread is quiet, I'll throw some uneducated opinions on it to help it along. >about the P[arrot|erl] interface on the >matter of converting low-level types. ord and chr are Perl functions for >doing two very specialized conversions, but I'm thinking Parrot needs to >provide a general-purpose number/[bit]?string conversion ala Perl's >pack/unpack so that all of the conversion functions for all of Parrot's >client languages can be written in terms of them. I was kind of surprised to see ord as a core op when I was doing BASIC. And had actually written my hack to go both ways (chr/ord) in an early version of the interpreter. >Certainly sprintf, pack and unpack in Perl should use some underlying >tool of Parrot's, and not re-invent the wheel (though each of those will >obviously do heavy argument processing in a Perl-specific way, some of >which I've already done for sprintf). > >Should these conversions be individual instructions (e.g. "uint2string") >or should there be a single-target "pack" analog in the PBC? I like the idea of having a single pack/unpack instruction, with some kind of argument mechanism to determine exactly how to pack. I don't know of an analogue in other CPU instruction sets (except maybe BCD ops in 8086), as they're typically not interested in something as high minded as some of this is. And while we're wishing, I'm certain I wouldn't want it as platform dependant as Perl's pack() is. I'd like to be able to easily determine if I'm working with native ints or some other kind of int. If I want to I'd like to pack my ints to 16, 32, or 64 bits on a whim. Use BCD and BER and any other strange encoding schemes I want. And I want a pony, too. Something else to throw into the discussion is whether we want to use a template (at the PBC level) as pack does or not. My initial gut reaction is no, because then we'd wind up with things like: pack S0, "ccxxcc", P0 # where P0 is a PerlArray or something And I'm not sure if 1. the pack target should be a "string" or not and 2. if I really want to have to mess with a PerlArray just to do some byte-shifting in PBC. But not using a template means having to possibly execute lots of instructions to disassemble the source piece-by-piece, and keeping this canned set of PBC around as a library to do common functions. Then again, I drool at the prospect of doing an sprintf in PASM...
Re: [PASM] problem opening / reading file
At 02:27 AM 8/13/2002 -0400, Dan Sugalski wrote: >At 11:13 PM -0400 8/12/02, Clinton A. Pierce wrote: >>At 10:04 PM 8/12/2002 +0200, Jerome Quelin wrote: >> >>>I looked at parrot_assembly.pod and saw: >>>open px, sy >>>Open the file Y on filehandle X >>>read px, py, pz >>>Issue a read on the filehandle in y, and put the >>>result in PMC X. PMC Z is the sync object. >> >>Ow. The I/O still hurts my head even now. It seemed to be an ugly >>stepchild at the time. > >Anyone up to throwing a list of outstanding problems with the I/O system >together? We need to get I/O off of Melvin's altogether too-full plate >before his wife hunts me down and does nasty things, so this'd be a good >place to start. I'd volunteer, except that I'm used to grunging around at the assembler level of I/O (INT 21h!) or with C's stdio and I don't think that your goal is either one of these targets. Frankly too, I don't understand the reasons and goals behind the monstrous complexity of Perl 6 and latter Perl 5's I/O. If you simply want a list of what we have outlined in core_ops, what works, what doesn't, and what's needed for a primitive I/O system... THAT I could piece together.
Re: [PASM] problem opening / reading file
At 10:04 PM 8/12/2002 +0200, Jerome Quelin wrote: >I looked at parrot_assembly.pod and saw: >open px, sy >Open the file Y on filehandle X >read px, py, pz >Issue a read on the filehandle in y, and put the >result in PMC X. PMC Z is the sync object. Ow. The I/O still hurts my head even now. It seemed to be an ugly stepchild at the time. >So, what am I doing wrong? What's the real syntax? (I wish there were a >parrotopentut ;) ). I don't think the I/O's quite mature enough for something like a tutorial. I've got a couple of examples in the BASIC source code. They are: basic.pl -- Where the immediate mode command is read. Nothing special here. Note though that I run the command through a STRIPSPACE (alpha.pasm) routine which removes trailing whitespace. You get the newlines here, and in Win32 PASM I've seen inconsistencies as to what exactly this means (one char or two). These may be fixed now. instructions.pasm -- Look down where the LOAD instruction is processed. Since there's isn't (or wasn't) a functional line-read PASM instruction I wind up reading the whole damndable file into a buffer and splitting it back out into an array. Also note that errors on the open are silently ignored. I don't think they work right yet. Or they didn't. The EOF detection didn't work IIRC, but checking for a zero-length read was good enough at the time. [Line I/O from files seems strange but Line I/O from the tty is just peachy. *shrug*] Also the INPUT routine does some line I/O just like basic.pl. >While I'm at reading files - why isn't there a readline op for file handles? >Is it planned / forbidden for an unknown (to me) reason / other (patches >welcome :o) )? *shrug* >Another question. Is there a way to fetch command line arguments, such as: >$ ./parrot foo.pbc foo bar baz Thanks for asking this, as Simon Glover's answer was... informative. Didn't know this before now.
Re: .include directive for new assembler
At 09:37 PM 6/21/2002 -0500, brian wheeler wrote: >I've implemented a .include directive for the new assembler. It >basically changes the preprocessor to shift through the source file, and >when an include is found, the included file is unshifted to the >beginning. To the beginning? Do we have any pre-processor directives (.constant, etc...) that are sensitive to where they're done? Either way, I'm fine with it. As soon as it's in, I'll fix BASIC to remove the hand-rolled .include stuff it has now.
[netlabs #716] Keyed hash access causes spurious "Cannot fetch string out of non-string key!" error
# New Ticket Created by "Clinton A. Pierce" # Please include the string: [netlabs #716] # in the subject line of all future correspondence about this issue. # http://bugs6.perl.org/rt2/Ticket/Display.html?id=716 > Background: String variables in BASIC are stored in the P21 PMC. When I ty to set a variable I say: save "variablename" save "value" bsr SSTORE And to restore it I call: save "variablename" bsr SFETCH The code for these is located in basicvar.pasm and for your convenience: SSTORE: pushs restore S1 # Value restore S0 # Name set P21[S0], S1 pops ret SFETCH: pushs pushi restore S0 # Name set S1, P21, S0 length I0, S1 # Works around an odd bug (may no longer exist) ne I0, 0, SNOTNULL set S1, "" SNOTNUL: save S1 popi pops ret When I run this code the store looks like this (from parrot -t): PC=2241; OP=703 (bsr_ic); ARGS=(-1043) PC=1198; OP=676 (pushs) PC=1199; OP=693 (restore_s); ARGS=(S1="Y") PC=1201; OP=693 (restore_s); ARGS=(S0="HELLO") PC=1203; OP=215 (set_keyed_p_s_s); ARGS=(P21=002F8040, S0="Y", S1="HELLO") PC=1207; OP=672 (pops) PC=1208; OP=738 (ret) The bsr's there, the push, two restores and the proper call to set_keyed. Now when I go to fetch that value: PC=5277; OP=703 (bsr_ic); ARGS=(-4068) PC=1209; OP=676 (pushs) PC=1210; OP=674 (pushi) PC=1211; OP=693 (restore_s); ARGS=(S0="Y") PC=1213; OP=152 (set_s_p_s); ARGS=(S1="Y", P21=002F8040, S0="Y") Cannot fetch string out of non-string key! There's the bsr, I save off the string and integer pointers restore the variable name to fetch and then try to fetch it...and it crashes. Notes: * Other than the "new", these are the only keyed accesses to P21 in the trace. * To reproduce for yourself: 1. Start basic.pl 2. Type LET Y$='HELLO' 3. Type PRINT Y$ * Curiously enough, fetching on a key that doesn't yet exist doesn't (and correctly doesn't) throw this error and just returns the empty string. [So if you leave off the LET Y$ part of the example off, it works fine.] Good luck.
[netlabs #702] BASIC causes sevg's in parrot
# New Ticket Created by "Clinton A. Pierce" # Please include the string: [netlabs #702] # in the subject line of all future correspondence about this issue. # http://bugs6.perl.org/rt2/Ticket/Display.html?id=702 > To reproduce, sync with CVS, build, run "basic.pl" -- that's all. This version of BASIC is unchanged since it last worked The error produced is: The memory at location 0x00025 could not be "written" The last thing in the Parrot trace is a "concat" statement, yet the call stack seems to indicate that Parrot's in some hash code. More information available upon request. The last instructions run by Parrot: PC=312; OP=571 (save_i); ARGS=(I1=1) PC=314; OP=560 (popi) PC=315; OP=562 (pops) PC=316; OP=628 (ret) PC=979; OP=580 (restore_i); ARGS=(I0=9) PC=981; OP=388 (length_i_s); ARGS=(I1=1, S0="LO") PC=984; OP=206 (ne_i_ic_ic); ARGS=(I1=2, 0, 12) PC=996; OP=182 (eq_i_ic_ic); ARGS=(I4=1, 0, 13) PC=1000; OP=204 (ne_i_i_ic); ARGS=(I0=1, I4=1, 9) PC=1004; OP=378 (concat_s_s); ARGS=(S0="LO", S1="A") The C call stack: buffer_lives(Buffer * 0x0251) line 291 + 4 bytes mark_hash(Parrot_Interp * 0x002f23a0, _hash * 0x002f7150, PMC * 0x0049d9d8) line 182 PARROT! Parrot_PerlHash_mark + 20 bytes trace_active_PMCs(Parrot_Interp * 0x002f23a0) line 391 + 12 bytes Parrot_do_dod_run(Parrot_Interp * 0x002f23a0) line 531 get_from_free_pool(Parrot_Interp * 0x002f23a0, Resource_Pool * 0x002f2750) line 87 new_string_header(Parrot_Interp * 0x002f23a0, unsigned long 0) line 574 string_make(Parrot_Interp * 0x002f23a0, const void * 0x, unsigned long 3, const parrot_encoding_t * 0x004291b8 _singlebyte_encoding, unsigned long 0, const parrot_chartype_t * 0x00429358 _usascii_chartype) line 50 string_concat(Parrot_Interp * 0x002f23a0, parrot_string_t * 0x002fe9d0, parrot_string_t * 0x002fe990, unsigned long 1) line 278 Parrot_concat_s_s(long * 0x00499420, Parrot_Interp * 0x002f23a0) line 1782 + 38 bytes PARROT! runops_fast_core + 26 bytes runops_generic(long * (Parrot_Interp *, long *)* 0x004011fd, Parrot_Interp * 0x00418cd0 _runops_fast_core, long * 0x002f23a0) line 80 + 21 bytes PARROT! runops_fast_core address 0x00418cd0 MSVCRT! 780115fb() Parrot_runcode(Parrot_Interp * 0x0001, int 1, char * * 0x002feb50) line 253 main(int 1, char * * 0x002f3c14) line 50 PARROT! mainCRTStartup + 227 bytes KERNEL32! 77e87903()
Re: [netlabs #700] Win32 parrot.exe fails all tests
At 10:54 PM 6/10/2002 +, you wrote: ># New Ticket Created by "Clinton A. Pierce" ># Please include the string: [netlabs #700] ># in the subject line of all future correspondence about this issue. ># http://bugs6.perl.org/rt2/Ticket/Display.html?id=700 > > > >After correcting the build problem with MSVC (stock MSVC++ 6.0, AS Perl, >etc..) noted earlier, Parrot now builds but fails all tests. > >No warnings during compilation, no errors. > >The error reported for each test is: > > Parrot VM: Can't unpack packfile .pbc > >Fill in /x+/ with your favorite compiled program. The assembler and >disassembler both like the resulting .pbc's but nothing will run in >parrot. If you'd like further details, let me know what you want and I'll >be happy to send you config info, compiled pbc's, etc.. The patch supplied by Jason seems to cure this problem (but not entirely). AFAIK it's not been applied though.
[netlabs #700] Win32 parrot.exe fails all tests
# New Ticket Created by "Clinton A. Pierce" # Please include the string: [netlabs #700] # in the subject line of all future correspondence about this issue. # http://bugs6.perl.org/rt2/Ticket/Display.html?id=700 > After correcting the build problem with MSVC (stock MSVC++ 6.0, AS Perl, etc..) noted earlier, Parrot now builds but fails all tests. No warnings during compilation, no errors. The error reported for each test is: Parrot VM: Can't unpack packfile .pbc Fill in /x+/ with your favorite compiled program. The assembler and disassembler both like the resulting .pbc's but nothing will run in parrot. If you'd like further details, let me know what you want and I'll be happy to send you config info, compiled pbc's, etc..
Parrot build failure, Win32 (missing include apa/inet.h?)
Standard MSVC++ 6.0 setup, last known to work: Thursday. Updated with completely clean tree, built with defaults (as I always do) and here's how it went: C:\projects\parrot\parrot>perl Configure.pl Parrot Version 0.0.6 Configure 2.0 Copyright (C) 2001-2002 Yet Another Society Hello, I'm Configure. My job is to poke and prod your system to figure out how to build Parrot. The process is completely automated, unless you passed in the `--ask' flag on the command line, in which case it'll prompt you for a few pieces of info. Since you're running this script, you obviously have Perl 5--I'll be pulling some defaults from its configuration. Checking MANIFEST...done. Setting up Configure's data structures...done. Checking for --miniparrot...done. Loading platform hints file...done. Determining what C compiler and linker to use...done. Determining what types Parrot should use...done. Determining what opcode files should be compiled in...done. Setting up experimental systems...done. Probing for C headers...done. Determining some sizes...done. Computing native byteorder for Parrot's wordsize...done. Figuring out how to pack() Parrot's types...done. Figuring out what formats should be used for sprintf...done. Determining if your C compiler is actually gcc...done. Determining architecture, OS and JIT capability...done. Verifying that the compiler supports function pointer casts...done. Determining if your compiler supports computed goto...done. Generating config.h...done. Writing Parrot::Config module...done. Generating Makefiles...done. Moving platform files into place...done. Okay, we're done! You can now use `make' (or your platform's equivalent to `make') to build your Parrot. After that, you can use `make test' to run the test suite. Happy Hacking, The Parrot Team C:\projects\parrot\parrot>nmake Microsoft (R) Program Maintenance Utility Version 6.00.8168.0 Copyright (C) Microsoft Corp 1988-1998. All rights reserved. C:\Perl\bin\perl.exe vtable_h.pl C:\Perl\bin\perl.exe make_vtable_ops.pl > vtable.ops C:\Perl\bin\perl.exe ops2c.pl C core.ops debug.ops io.ops rx.ops vtable.ops C:\Perl\bin\perl.exe ops2c.pl CPrederef core.ops debug.ops io.ops rx.ops vtable.ops cl -nologo -O1 -MD -DNDEBUG -DWIN32 -D_CONSOLE -DNO_STRICT-I./include -DHAS_JIT -DI386 -Fotest_main.obj -c test_main.c test_main.c cl -nologo -O1 -MD -DNDEBUG -DWIN32 -D_CONSOLE -DNO_STRICT-I./include -DHAS_JIT -DI386 -Foexceptions.obj -c exceptions.c exceptions.c ../include\parrot/parrot.h(66) : fatal error C1083: Cannot open include file: 'arpa/inet.h': No such file or directory NMAKE : fatal error U1077: 'cl' : return code '0x2' Stop. C:\projects\parrot\parrot>
PATCH for Win32 lib/Parrot makefile woes
Fixes the problem where the toplevel makefile can't descend into lib/Parrot to do the build necessary for PackFile and friends. Also I think the single cd .. may potentially be a bug for other platforms as well. Apply this and re-run Configure.pl and all is well. --- config/gen/makefiles/root.in_oldTue Jun 04 15:45:49 2002 +++ config/gen/makefiles/root.inTue Jun 04 15:42:42 2002 @@ -408,7 +408,7 @@ #newasm : $(TEST_PROG) lib/Parrot/.dummy lib/Parrot/.dummy : - cd lib/Parrot && $(PERL) Makefile.PL && $(MAKE) && cd .. + cd lib && cd Parrot && $(PERL) Makefile.PL && $(MAKE) && cd .. && cd .. docs/.dummy : cd docs && $(MAKE) && cd ..
[netlabs #658] Disassembler will not disassemble BASIC
# New Ticket Created by "Clinton A. Pierce" # Please include the string: [netlabs #658] # in the subject line of all future correspondence about this issue. # http://bugs6.perl.org/rt2/Ticket/Display.html?id=658 > The disassembler will take apart small .pbc files, but will not tackle BASIC's pbc. I don't think I've actually posted a real bug for this (just whined before) so here it is. The error generated is: C:\projects\parrot\parrot>disassemble.pl languages\BASIC\basic.pbc Use of uninitialized value in modulus (%) at lib/Parrot/Types.pm line 102, line 11. Use of uninitialized value in addition (+) at lib/Parrot/Types.pm line 103, line 11. Use of uninitialized value in substr at lib/Parrot/Types.pm line 105, line 11. PackFile::ConstTable: Internal error: Unpacked Constant returned bad byte count '52'! at lib/Parrot/ PackFile/ConstTable.pm line 73 Parrot::PackFile::ConstTable::unpack('Parrot::PackFile::ConstTable=HASH(0x1d3d334)', 'l^@^@^ @s^@^@^@^T^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^A^@^@^@-^@^@^@s^@^@^@^T^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^A^@^@ ^@A^@^@^@s^@^@^@...') called at lib/Parrot/PackFile.pm line 226 Parrot::PackFile::unpack('Parrot::PackFile=HASH(0x1d3d358)', '^D^@^@^@^@^@^@^@^@^@^@^@^@^@^@ ^@M-!U1^ALREP^@^@^@^@M-h^N^@^@l^@^@^@s^@^@^@^T^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^A^@^@^@-^@^@^@...') cal led at lib/Parrot/PackFile.pm line 283 Parrot::PackFile::unpack_filehandle('Parrot::PackFile=HASH(0x1d3d358)', 'FileHandle=GLOB(0x1 d3d418)') called at lib/Parrot/PackFile.pm line 299 Parrot::PackFile::unpack_file('Parrot::PackFile=HASH(0x1d3d358)', 'languages\BASIC\basic.pbc ') called at C:\projects\parrot\parrot\disassemble.pl line 248 main::disassemble_file('languages\BASIC\basic.pbc') called at C:\projects\parrot\parrot\disa ssemble.pl line 284 To recreate the error, run the basic.pl script, QUIT out of BASIC and then attempt to disassemble the basic.pbc file.
New assembler problem, with fix.
I'm not at a system where diff/patch runs, but here's a fix for you. In _string_constant you're trying to expand \n and friends with: $constant = eval "qq($constant)"; This breaks if the token ) appears in $constant. Changing () to anything else breaks if that anything else is in the string too. After thinking on this long and hard, here's a replacement bit of code: local $_=substr($constant,0,1); $constant =~ s/\$/\\\$/g; $constant = $_ . eval("qq$constant") . $_; warn "Constant: $@ " if $@; This uses the constant's own delimiter (" or even ') as the delimiter for the eval. It also escapes $'s so that things like $a don't interpolate or cause other errors. (I suppose @ should be guarded against too. Ah well..) With this fix and the recently committed changes I made to BASIC... it now compiles and runs fine.
Re: Win32 build broken
At 07:13 AM 6/2/2002 +0200, Sebastian Bergmann wrote: >cd lib/Parrot && C:\Programme\Perl\bin\perl.exe Makefile.PL && NMAKE && >cd .. >Can't open perl script "Makefile.PL": No such file or directory >NMAKE : fatal error U1077: 'cd' : Rueckgabe-Code '0x2' >Stop. Changing that to: cd lib\Parrot && C:\Programme\Perl\bin\perl.exe Makefile.PL && NMAKE && cd .. in the Makefile will fix the problem and allow the build to continue. I'm not sure of what the correct fix is, or I'd offer a patch... [Even if the build completes the tests don't run anymore on Win32 MSVC due to errors in the bytecode...]
Re: [COMMIT] New Assembler in place
At 04:39 PM 6/1/2002 -0400, Melvin Smith wrote: >At 02:25 PM 6/1/2002 -0400, Clinton A. Pierce wrote: > >Looks great. Converted over with little sweat, noted below. > >Moving in the right direction. mandelbrot.cola -> mandel.pasm >[...] >Thats about 37% of the old assemble time. I noticed that too. If I could just find out why the Parrot bytecode being emitted by the assembler for BASIC is no good, I'd be happy!
Re: [COMMIT] New Assembler in place
>This should actually be: > >".constant PerlHash 6" > >Right? Someone's mailer is adding an extra .
Re: [COMMIT] New Assembler in place
I'm in the process of converting BASIC over to use this new assembler... and have hit a few snags. I'm happy to patch, but don't know if this is the Right Thing or not. At 12:39 AM 6/1/2002 -0400, you wrote: >Support for keyed parameters now exists. I need to change the name of >the 'set_keyed' and 'get_keyed' operator to just 'set', since they >should be relatively unambiguous. Anyway, here's the new syntax >available at the assembly level: Looks great. Converted over with little sweat, noted below. >The next feature which Clinton used in his BASIC compiler but had to do >by hand is a manifest constant. You can use the following syntax to >define an assemble-time constant: > >..constant PerlHash 6 # Important, because the special names 'PerlHash' This should actually be: ..constant PerlHash 6 Right? I was doing a simple X for Y transformation using a pattern like this: ^.const\s+(\w+)\s+(.*) This let me rename registers for sake of clarity. I'm missing that. It's a simple hack, just add an elsif block that looks like: } elsif(/^\.constant \s+ (\w+)\s+ ([NISP]\d+) /x) { # .constant {name} {string $self->{constants}{$1} = $2; } Other things to note: The assembler seems unhappy with multiple labels for the same codepoint. This is no longer allowed: NSORT: COMBSORT: operation To allow a bsr NSORT or a bsr COMBSORT to jump to the same instruction you now have to write: NSORT: noop COMBSORT: operation And it works fine. The keyed operators get_keyed, set_keyed are unhappy with constants: get_keyed S0, P0[0] For example. Writing them the old way still works. After all this, and checking it in I still can't get BASIC to assemble correctly. The last remaining error I get is: C:\projects\parrot\parrot\languages\BASIC>..\..\parrot.exe basic.pbc PackFile_Constant_clear: Unrecognized type ' ' during unpack! PackFile_unpack: Error reading constant table segment! Parrot VM: Can't unpack packfile basic.pbc. BASIC's all checked in with the corrections noted above. I patched my version of assemble.pl to allow register redefinition (.constant FOO I0). But other than that, once this last error is found it's ready to go. Suggestions?
Re: BF interpreter
At 11:09 AM 5/30/2002 +0100, Leon Brocard wrote: >Hello. > >I've been looking at languages to run under Parrot, and I choose a >certain language which is turing complete in eight instructions. Start >with the small ones eh? Unfortunately its name is not family >friendly. An interpreter is attached, although you'll need to add the >chr() operator (see the patch). A BF compiler would be neat too, of >course. Interesting. :) If you'd like a pure-PASM chr() operator, see the BASIC interpreter in expr.pasm. I essentially do (everything in BASIC is on the stack...excuse the restore and saves...): FUNC_CHR: # ... other stuff ... restore I0 # The number to convert gt I0, 255, FUNC_ASCII_ERROR bsr SET_S1_ASCII substr S0, S1, I0, 1 save S0# The corresponding character branch ENDFUNCDISPATCH SET_S1_ASCII: set S1, "\x0\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10\x11\x12\x13\x14\x15\x16\x17\x1 8\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x3 1\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4 a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x6 3\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7 c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x9 5\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xa e\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc 7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe 0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf 9\xfa\xfb\xfc\xfd\xfe\xff" ret BF would use this a lot more than BASIC would, so instead of just throwing the table into S1 whenever it's called you might want to keep it around. To convert the other way (ASC) I take the character and perform a search on S1 and the offset is the ASCII code. Just a thought.
Re: New Assembler for your perusal
At 09:17 AM 5/26/2002 +0200, Sebastian Bergmann wrote: >Jeff wrote: > > newasm has been completely rewritten. Three surprises lurk within. > >sb@wopr-mobile:/usr/src/parrot> newasm >Can't locate auto/Parrot/PakFile2/autosplit.ix Go into lib/Parrot and perl Makfile.pl && make and then try it again. Works okay for me. Well, almost. Still can't get BASIC to assemble. Looking at that probably tonight...
Using BASIC for testing.
Since the topic of using BASIC as part of the test suite for Parrot has been brought up before I'll mention a recent change I made here which might make this easier. If the BASIC interpreter is invoked now, and a file named "autorun.bas" exists in the same directory, it will be run by the interpreter auto-magically on startup. At the moment I'm using this to run the BASIC regression test while I'm modifying the interpreter so I can just say (in vim): !basic.pl Have it assemble up BASIC, run the test (which had been renamed to autorun.bas) and exit back to vim. Earlier this evening I was using it to run a BASIC CGI script (just for kicks). Making the last instruction "QUIT" will exit the interpreter when autorun.bas is finished running; making the last instruction "NEW" will clear memory and leave you in interactive mode. Otherwise you're dropped into interactive mode when the program's done running.
Accidental Coverage Map
[From the "I Just Thought I'd Share" file.] I was trying to trace down a bug in BASIC (which later turned out to be a bug in how I thought) and I got stuck at the point where I had a tracefile that led up to the crash. I got the trace with parrot's trace instruction. In BASIC I've got a built-in named "TRACE" to toggle it. So I said: C:\projects\parrot\languages\basic\>basic.pl 2>tracefile Including stackops.pasm Including alpha.pasm Including dumpstack.pasm Including tokenize.pasm Including basicvar.pasm Including basic.pasm Including instructions.pasm Including expr.pasm 3727 lines Ready LOAD wumpus LOADING wumpus.bas...DONE Ready TRACE 1 Ready RUN So now I've got the parrot trace going out to tracefile. Once the program crashed (again my fault) I could tail the tracefile and it'd show me the last instructions evaluated. Of course, I have no idea what those really correlate to in the BASIC PASM source because all I get are the Program Counters. This is not a fun way to spend Friday night. And the disassembler is broken again, so I couldn't use that. So I filtered the tracefile through this bit o Perl and sent it to a file named "output": open(T, "tracefile") || die; $|++; while() { next unless /^PC=(\d+);\sOP=\d+\s\((\w+)\)/; $pc{$1}=$2; } foreach(sort { $a <=> $b } keys %pc) { print "PC=$_ $pc{$_}\n"; } So now I've got all of the instructions executed during the run sorted in PC order in "output"... And I've got the original PASM in a file called "test.pasm" (an intermediate file that basic.pl creates)... Most importantly I've got Perl. So I hacked together this little script: open(P, "test.pasm") || die "test.pasm: $!"; @program=; chomp(@program); close(P); open(T, "outfile") || die "tracedump: $!"; @trace=; chomp(@trace); close(T); sub neat { my($pc,$lab,$code)=@_; $pc=" " if $pc<0; $lab=" " unless $lab; $code=~s/^\s+//g; printf("%5s %8s %s\n", $pc, $lab, $code); } foreach(@program) { $orig=$_; if (/^\s*#/) { s/^\s+//; neat(-1, "", $orig); next; } if (/^\s*$/) { next; } if (m/^\s*(\w+):/) { # Label neat(-1, "${1}:", ""); s/^\s*\w+:\s*//; # Remove it redo; } s/^\s*//; if (! m/^([a-z]+)/) { die "Syntax error? $orig"; } $_=$1; if (@trace) { $instr=$trace[0]; $instr=~m/PC=(\d+)\s+([a-z]+)/; if ($_ eq $2) { neat($1, "", $orig); shift @trace; } else { neat(-1, "", $orig); } } } What it effectively does is merge the tracefile with the original PASM to give me 1. a mapping from PC to the original source code and 2. an execution coverage map for the program against the source code. The output looks something like: # Okay, found an ) went back to (, is the next thing a ~ ? TILDECK: 4477 bsr OPSTACKDEPTH 4479 restore I0 4481 eq I0, 0, GETTOP # Nope, apparently not. 4485 bsr POPOPSTACK 4487 set S1, "" 4490 restore S1 4492 eq S1, "~", GOTTILDE save S1 bsr PUSHOPSTACK # Oops, sorry. branch GETTOP GOTTILDE: 4502 concat S0, S1 # Mash that tilde on there. 4505 concat S0, "|" 4508 branch GETTOP CANPUSH: Which tells me a few things. First that the second bsr PUSHOPSTACK was never executed, and when I went looking for instruction at PC 4481 I went right to the correct place in the PASM and found my problem. (Which turned out to be a typo in the BASIC program I was working on! :) With a small modification, I can get output which shows me how many times each instruction (in the source) was executed. It's not perfect. There are places where it thinks it's found the instruction to match up with the PC and guesses wrong (it corrects shortly thereafter). Eventually I'd like to hack something like this into the assembler, but for now this suffices.
Re: [netlabs #613] Parrot BASIC SEGV's with much string handling
[re-cc'd p6i due to mailer failure on my part] >At 10:17 PM 5/22/2002 +, via RT wrote: >Clinton A. Pierce wrote: > >> * sync up, and get the latest Parrot BASIC. It's fully hash-enabled and >> quite speedy now. >> >> * Run "basic.pl" to assemble the interpreter, and get it started >> >> * At the "Ready" prompt, "LOAD eliza" >> >> * When finished, type RUN >> >> The crash will happen shortly thereafter. Comments in #parrot seem to > >The problem appears to originate in the routine SFETCH, which tries to fetch >key "TWIRL" from the hash in P21 without finding it. The hash code returns a >null pointer under these circumstances, which is accepted as an empty string >by some, but not all, string handling code. In this case, attempting to >store the string into an array is invoking string_copy, which assumes the >input to be valid. IIRC Dan stated some time ago that checks for null were >not to be included, but I don't know what the current status is. A patch to add isnull was submitted today, which is one potential way of handling it. Another is to not have get_keyed return the NULL in the first place. I favor the latter, because there's no other way that I'm aware of in PASM to get an Sx register with a NULL in it, why start introducing this now? It seems unclean. (But a patch oftentimes speaks louder than opinions.) So temporarily I patched basicvar.pasm so that instead of: SFETCH: pushs pushi restore S0 # Name get_keyed S1, P21, S0 save S1 popi pops ret I do this as I'm fetching the (possibly non-existent) value from the hash: SFETCH: pushs pushi restore S0 # Name get_keyed S1, P21, S0 length I0, S1 ne I0, 0, SNOTNULL set S1, "" SNOTNULL: save S1 popi pops ret Because length Ix, Sx seems to be immune from the NULL problem. Now BASIC and all of its demo programs run without a hitch. This could easily be fixed with "isnull Sx, label" also.
[netlabs #613] Parrot BASIC SEGV's with much string handling
# New Ticket Created by "Clinton A. Pierce" # Please include the string: [netlabs #613] # in the subject line of all future correspondence about this issue. # http://bugs6.perl.org/rt2/Ticket/Display.html?id=613 > I do not have a short test for this one. To reproduce this problem: * sync up, and get the latest Parrot BASIC. It's fully hash-enabled and quite speedy now. * Run "basic.pl" to assemble the interpreter, and get it started * At the "Ready" prompt, "LOAD eliza" * When finished, type RUN The crash will happen shortly thereafter. Comments in #parrot seem to indicate that this is "a bus error in the garbage collector" [None of the other BASIC programs will trigger this error.]
[netlabs #612] Divide by Zero error in hash key retrieval
# New Ticket Created by "Clinton A. Pierce" # Please include the string: [netlabs #612] # in the subject line of all future correspondence about this issue. # http://bugs6.perl.org/rt2/Ticket/Display.html?id=612 > In converting BASIC to use hashes, I discovered that once in a great while the OS will throw the error: The exception Integer division by zero (0xc094) occured in the applicaiton at location 0x00417fce The cause is retrieving a key that does not yet exist in the hash. This is probably not the right thing to do. In fact, I'm convinced, that a few days ago the value 0 would have been retrieved. (Without "exists" I'm kinda groping around here...) Going into MSVC's debugger, the statement that it doesn't like is: return find_bucket(interpreter, chain, key); And the call stack looks like: hash_lookup() hash_get() Parrot_Perl_hash_get_integer_keyed Parrot_get_keyed_i_p_s runops_fast_core And so on. The last PASM instruction run was: get_keyed_i_p_s ARGS I1=0, P20=004AAEF0, S0="I" I'm betting this was caused by fetching a key that did not yet exist. :)
Re: New assembler difficulties.
At 10:29 AM 5/19/2002 +0100, Simon Cozens wrote: > > > Unparsable argument, starting from '"', QUOTE > > > No line number, no context, nearly impossible to find to debug. > >That's an internal error with the assembler, shouldn't happen. It >suggests the string regexp is broken. I deliberately didn't add contextual >information because I wanted the assembler to be machine-oriented rather >than human-oriented, and we can depend on machines to produce well-formed >bytecode or it's an internal error on *their* side. I suggest that at some point an input line number should probably be generated in the message. At the very least because some poor schmuck has to actually write software to generate these machine-oriented instructions and he's gonna need to debug his own programming. The assembler knows there's a problem, it knows about where, we should throw the poor guy a bone.
Re: New assembler difficulties.
At 09:27 PM 5/18/2002 -0400, Jeff wrote: > > So the new assembler's unhappy. Suggestions? > >Well, it's unhappy when you do lots of things. The code I was given was >not as complete/functional as I had been led to believe, inasmuch as it >doesn't live past test series 2 without some major tweaks that I'm >working on. And I'm not even going to comment on t/pmc... However, none >of this minor rant has anything to do with your problem. > >I can't reproduce it locally, so I'm wondering if the Windows build >might not properly expand the Perl_croak call from 'Perl_croak("foo")' >to 'Perl_croak(aTHX_ "Foo")', as the UNIX .xs build does... 1. You're right, it's not expanding at all under Win32. Adding the aTHX_ makes this compile. 2. The Makefile's looking for things like bytecode.o when under Win32 it should be bytecode.obj 3. After all this, the assembler will compile small programs. Feeding it BASIC produces lots of warnings about uninitalized values and finally dies with: Unparsable argument, starting from '"', QUOTE No line number, no context, nearly impossible to find to debug. I think you're right, and you were given a pig in a poke.
New assembler difficulties.
So here I am, hacking BASIC to use keyed PMC's for variables to make it blazingly fast when I find out that to do this I need to use the new assembler. So I pop into lib\parrot and proceed with the build and I get this mess: C:\projects\parrot\parrot\lib\Parrot>perl makefile.pl Writing Makefile for Parrot::PakFile2 C:\projects\parrot\parrot\lib\Parrot>nmake Microsoft (R) Program Maintenance Utility Version 6.00.8168.0 Copyright (C) Microsoft Corp 1988-1998. All rights reserved. cp Op.pm blib\lib\Parrot\Op.pm cp OpTrans.pm blib\lib\Parrot\OpTrans.pm cp OpsFile.pm blib\lib\Parrot\OpsFile.pm cp Assembler.pm blib\lib\Parrot\Assembler.pm cp PMC.pm blib\lib\Parrot\PMC.pm cp Config.pm blib\lib\Parrot\Config.pm cp PackFile.pm blib\lib\Parrot\PackFile.pm cp String.pm blib\lib\Parrot\String.pm cp Types.pm blib\lib\Parrot\Types.pm cp Test.pm blib\lib\Parrot\Test.pm cp BuildUtil.pm blib\lib\Parrot\BuildUtil.pm cp PakFile2.pm blib\lib\Parrot\PakFile2.pm AutoSplitting blib\lib\Parrot\PakFile2.pm (blib\lib\auto\Parrot\PakFile2) cp Vtable.pm blib\lib\Parrot\Vtable.pm cp Optimizer.pm blib\lib\Parrot\Optimizer.pm C:\Perl\bin\perl.exe -IC:\Perl\lib -IC:\Perl\lib C:\Perl\lib\ExtUtils/xsubpp -typemap C:\Pe rl\lib\ExtUtils\typemap PakFile2.xs > PakFile2.xsc && C:\Perl\bin\perl.exe -IC:\Perl\lib -IC:\Perl\l ib -MExtUtils::Command -e mv PakFile2.xsc PakFile2.c Please specify prototyping behavior for PakFile2.xs (see perlxs manual) cl -c -I../../include -nologo -O1 -MD -DNDEBUG -DWIN32 -D_CONSOLE -DNO_STRICT -DHAVE_DES_FCR YPT -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -DPERL_MSVCRT_READFIX -O1 -MD -DNDEBUG-DVERSION= \"0.01\" -DXS_VERSION=\"0.01\" -IC:\Perl\lib\CORE PakFile2.c PakFile2.c PakFile2.xs(21) : warning C4133: 'function' : incompatible types - from 'char [52]' to 'struct inter preter *' PakFile2.xs(21) : error C2198: 'Perl_croak' : too few actual parameters PakFile2.xs(32) : warning C4133: 'function' : incompatible types - from 'char [40]' to 'struct inter preter *' PakFile2.xs(32) : error C2198: 'Perl_croak' : too few actual parameters PakFile2.xs(48) : warning C4133: 'function' : incompatible types - from 'char [52]' to 'struct inter preter *' PakFile2.xs(48) : warning C4047: 'function' : 'const char *' differs in levels of indirection from ' long ' PakFile2.xs(48) : warning C4024: 'Perl_croak' : different types for formal and actual parameter 2 PakFile2.xs(69) : warning C4133: 'function' : incompatible types - from 'char [36]' to 'struct inter preter *' NMAKE : fatal error U1077: 'cl' : return code '0x2' Stop. So the new assembler's unhappy. Suggestions?
Re: Eliza RFC
At 11:11 AM 4/30/2002 -0400, Melvin Smith wrote: >Now that Clint has Eliza running on Parrot, I propose that >from henceforth, Eliza shall field all newbie questions >and take responsibility of the FAQ. [...] >WE WERE DISCUSSING YOU NOT ME. >we were DISCUSSING ELLOOPO! >SYMBOL NAME TOO LONG: we were DISCUSSING ELLOOPO|1,1 > >Apparently this could be construed as convincing Eliza, I'm not sure >though, I'll ask next session. The bug in BASIC/Eliza has been fixed and committed. It's unlikely you'll be able to convince Eliza to give you the elloopo feature now.
BASIC hangs and crashes, Win32 MSVC++, 0.0.5
Sometime during or shortly after the 0.0.5 release, BASIC broke with string/stack/GC errors. During program LOAD, Parrot runs off eats a ton of memory (sometimes) and falls over dead (eventually). Someone else in #parrot tried the exact same test without problems. I'm dismayed. To reproduce this bug under any post 0.0.5 CVS update: * Go into the languages/BASIC directory * Start basic using the handler: C:\projects\perl\parrot\languages\BASIC>basic.pl Including stackops.pasm Including alpha.pasm Including dumpstack.pasm Including tokenize.pasm Including basicvar.pasm Including basic.pasm Including instructions.pasm Including expr.pasm 4050 lines Ready * Immediately load wumpus (it won't finish): LOAD wumpus LOADING wumpus.bas... * Wait for segfault (it takes a couple of minutes on my P300). * While you're waiting, watch memory be eaten by Parrot. Calling the sweepoff and collectoff have no effect other than to make the memory-eating much more impressive (and the crash more spectacular). I've got Parrot compiled under Win32 (Win2k) with MSVC++. ** I'd like to offer that BASIC could somehow be incorporated into the test suite for Parrot? Would it help? It's awfully sensitive to problems with strings, stacks, etc. As a general rule, if you can get something like wumpus.bas to load and run in BASIC then things are healthier than not. I could modify BASIC to help. For example, an alternate basic.pl that would create a "batch" version of BASIC instead of an interactive one. (All of the interactive code is in that short Perl script.) To run BASIC in batch mode is simply a matter of replacing MAIN in basic.pl with a MAIN that does something like: save 0 # Seed the runtime stack save "LOAD wumpus" bsr RUNLINE save "RUN" bsr RUNLINE restore I0 # Run's status end This is how my test harness works so I don't have to type programs at it, or wear out my capslock key.
[netlabs #522] BASIC hangs and crashes, Win32 MSVC++, 0.0.5
# New Ticket Created by "Clinton A. Pierce" # Please include the string: [netlabs #522] # in the subject line of all future correspondence about this issue. # http://bugs6.perl.org/rt2/Ticket/Display.html?id=522 > Sometime during or shortly after the 0.0.5 release, BASIC broke with string/stack/GC errors. During program LOAD, Parrot runs off eats a ton of memory (sometimes) and falls over dead (eventually). Someone else in #parrot tried the exact same test without problems. I'm dismayed. To reproduce this bug under any post 0.0.5 CVS update: * Go into the languages/BASIC directory * Start basic using the handler: C:\projects\perl\parrot\languages\BASIC>basic.pl Including stackops.pasm Including alpha.pasm Including dumpstack.pasm Including tokenize.pasm Including basicvar.pasm Including basic.pasm Including instructions.pasm Including expr.pasm 4050 lines Ready * Immediately load wumpus (it won't finish): LOAD wumpus LOADING wumpus.bas... * Wait for segfault (it takes a couple of minutes on my P300). * While you're waiting, watch memory be eaten by Parrot. Calling the sweepoff and collectoff have no effect other than to make the memory-eating much more impressive (and the crash more spectacular). I've got Parrot compiled under Win32 (Win2k) with MSVC++. ** I'd like to offer that BASIC could somehow be incorporated into the test suite for Parrot? Would it help? It's awfully sensitive to problems with strings, stacks, etc. As a general rule, if you can get something like wumpus.bas to load and run in BASIC then things are healthier than not. I could modify BASIC to help. For example, an alternate basic.pl that would create a "batch" version of BASIC instead of an interactive one. (All of the interactive code is in that short Perl script.) To run BASIC in batch mode is simply a matter of replacing MAIN in basic.pl with a MAIN that does something like: save 0 # Seed the runtime stack save "LOAD wumpus" bsr RUNLINE save "RUN" bsr RUNLINE restore I0 # Run's status end This is how my test harness works so I don't have to type programs at it, or wear out my capslock key.
Re: [PATCH] Assembler Strings
I've been using single-quoted strings in the assembler interchangeably with double-quoted strings only because I couldn't find an easier way to say: set S0, 'Dan said, "UGH!"' Unless I used \ sequences for the double-quotes. Personally, I'm in favor of keeping ' and " functionally equivalent in the assembler -- just delimiters. Building too much smarts in the assembler (What'll we do with `` ?) is misdirected effort...
Re: [PATCH] Re: Is there a way to turn GC completely off?
At 01:05 AM 4/15/2002 -0400, you wrote: >Clint, in terms of getting things in Parrot fixed, I think it's better if >you can provide a way to generate the bug, no matter how complex the case >is. Non-simple test cases are better than no test cases at all, imo. Okay. Good. I won't spend a *terrible* amount of time trying to reduce larger problems to smaller ones. When I report a bug to bugs-perl6 this is where 95% of my time goes. I can isolate it to a few instructions, but chopping BASIC down to 30 or 40 lines of PASM that'll still trigger the bug is insanity. I'll work on saying "Hey, start BASIC, type 'foo' and watch Parrot explode" kinds of descriptions once I've positively determined that the bug isn't mine. >For example, I was able to reproduce the missing line 20 bug, and that was >fixed with Peter's patch. I played a few games of WUMPUS tonight on my >MSVC-compiled parrot, but haven't seen anything out of the ordinary. It >works flawlessly, and is really cool to see something like that working on >Parrot. The only things I could complain about would be case-sensitivity >in commands (it's annoying to keep the capslock key and get screwed up >when switching to other applications :), and the one or two seconds it >takes to generate the maze and set itself up. The case sensitivity could be eliminated if I had a cheap way of case-insensitively string comparing things. I may hack on that as there's only a few places where that's done: the huge switch in basic.pasm, a few places in instructions.pasm where multi-keyword instructions are parsed (IF..THEN) and the expression evaluator. I have a patch for the speed. For linear execution, it now "remembers" where the last code instruction was decoded from in storage and begins searching for the next program line there instead of the beginning (the 4/8 version has that). The patch I have allows FOR..NEXT and GOSUB..RETURN to use the same mechanism. The slow maze setup is due to a pair of doubly-nested FOR loops some ways down in the WUMPUS code. Once the patch is installed (I gotta test!) then the only slow jumps are GOTO branches forwards a long distance or backwards. Fully interpreted languages are slow, go figure. :) Once hashes are in place, then BASIC will get a whole lot faster. My Perl version of this interpreter (from which the PASM is derived) positively screams. To retro-fit this version of BASIC requires only that VFETCH, VSTORE and VCREATE be re-engineered with hashes when they're ready. >Do you have any test cases for reproducing the two bugs you just mentioned >in this thread? I will work on it today.
Re: [PATCH] Re: Is there a way to turn GC completely off?
At 08:55 PM 4/14/2002 +0200, Peter Gibbs wrote: >The specific problem Clinton mentioned is yet another infant mortality >problem, this time in string_concat. I don't know what the current decision >is on handling these situations, but this one can be avoided by optimising >the code anyway. If the transcoding is done before making the result string, >we know the actual length, instead of using the maximum possible. > >I haven't yet looked to see why basic needs to transcode string anyway. As a follow-up, I found one bug. Rather odd it is. The symptom is loading a program, doing a LIST and seeing only part of the code. Dumping the string-which-contains-the-code you can see the entire program in it (unlike the earlier described bug). The problem was in here: set S2, "" substr S2, S15, I1, LINEWIDTH save S2 bsr STRIPSPACE # (removes trailing whitespace) set I2, S2 # Quietly convert S2 to an int ge I2, I6, VFOUND So I'd pull things out of S15, strip the space off, look for something greater-than or equal-to I6. Problem was this test was *failing*. Putting diagnostics in I found out that S2 wasn't getting converted correctly to an integer in I2. *puzzle*. Changing the conversion part of the code to: save S2 bsr ATOI restore I2 Fixes the problem. The insane thing is that ATOI essentially loads a string register from the stack, coverts it, and then puts it back as an integer -- almost exactly what was failing before.
Re: [PATCH] Re: Is there a way to turn GC completely off?
At 08:55 PM 4/14/2002 +0200, Peter Gibbs wrote: >The specific problem Clinton mentioned is yet another infant mortality >problem, this time in string_concat. I don't know what the current decision >is on handling these situations, but this one can be avoided by optimising >the code anyway. If the transcoding is done before making the result string, >we know the actual length, instead of using the maximum possible. > >I haven't yet looked to see why basic needs to transcode string anyway. Both with the sweepoff/collectoff and your patch I'm still seeing the behavior I described at the top of this thread. In fact, the behavior I'm seeing is getting *worse* with recent CVS updates. Eeeek! Nothing works. *panic* I'm off for the evening, but I'll try to come up with a small test case if there is such a beast.
Re: Is there a way to turn GC completely off?
At 10:06 PM 4/13/2002 -0400, Dan Sugalski wrote: >At 5:35 PM -0400 4/13/02, Clinton A. Pierce wrote: >>I'm fighting a now-you-see-it now-you-don't kind of bug and I was >>wondering if there's a way to completely turn off garbage collection and >>memory re-use for debugging? > >Yes. The sweepoff and collectoff ops will turn of DOD runs and GC sweeps, >respectively. sweepon and collecton will re-enable them. (They are >attached to the counters, so they nest and you need to match off and on counts) > >Just added the things to CVS, so you'll need to resync to get 'em. Got 'em and tried them. Some bugs vanished, but others are still there. Hrm. At least I can eliminate some potential sources.
Is there a way to turn GC completely off?
I'm fighting a now-you-see-it now-you-don't kind of bug and I was wondering if there's a way to completely turn off garbage collection and memory re-use for debugging? My problems vanish when seemingly insignificant things happen, and re-appear again later. For example, I'll take a line of text (simplified): save S0 # "20 GOTO 10" bsr TOKENIZER restore I5 save VARWIDTH # (10) save " " bsr PAD restore S1 dec I5 concat S22, S1 # S22 is now "20" concat S22, S0 concat S22, TERMINATOR# S22 now reads "2020 GOTO 10#" bsr CLEAR # Clean stack Much later on, I'll look in S22 and find that the part that once read as it did above, now reads: "20 #" With the in-between text...vanished. Sometimes adding a diagnostic "print" statement makes it go away. Sometimes adding two makes it come back again. Having the interpreter handle some programs makes everything fine but just jumping in and loading WUMPUS right away makes it die. I'm completely positive I'm not clearing that piece of real estate...something else is doing it. But what, I dunno. Why, I know even less. [This causes the occasional "wrong type on stack" errors in BASIC. I get the error because I pull the line from S22 (which is now nothing but spaces) and attempt to extract the line number from it... and fail. This is really a Should Not Happen error because the line number was verified (in the real code) as it was stuck into S22. This can happen during a LOAD or RUN on typed-in programs where S22 gets populated. To see for yourself, start parrot basic and immediately type (and nothing else, no typos): 10 PRINT "HELLO WORLD" 20 GOTO 10 LIST And the listing will have a blank line 20 under Win32, recent builds of parrot. If you type an empty line anywhere in this process (just a return) or any other keywords after the Ready prompt the problem goes away magically.]
[netlabs #500] disassemble fails with errors and garbage
# New Ticket Created by "Clinton A. Pierce" # Please include the string: [netlabs #500] # in the subject line of all future correspondence about this issue. # http://bugs6.perl.org/rt2/Ticket/Display.html?id=500 > Compiling BASIC into out.pbc: C:\projects\parrot\parrot>basic.pl [produces out.pbc] Including stackops.pasm Including alpha.pasm Including dumpstack.pasm Including tokenize.pasm Including basicvar.pasm Including basic.pasm Including instructions.pasm Including expr.pasm 4026 lines Ready QUIT C:\projects\parrot\parrot>disassemble.pl out.pbc Use of uninitialized value in modulus (%) at lib/Parrot/Types.pm line 82, line 12. Use of uninitialized value in addition (+) at lib/Parrot/Types.pm line 83, line 12. Use of uninitialized value in substr at lib/Parrot/Types.pm line 85, line 12. PackFile::ConstTable: Internal error: Unpacked Constant returned bad byte count '52'! at lib/Parrot/PackFile/ConstTable.pm line 73 Parrot::PackFile::ConstTable::unpack('Parrot::PackFile::ConstTable=HASH(0x1d48340)', 'm^@^@^ @s^@^@^@^T^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@#^@^@^@s^@^@^@^T^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@ ^@-^@^@^@s^@^@^@...') called at lib/Parrot/PackFile.pm line 149 Parrot::PackFile::unpack('Parrot::PackFile=HASH(0x1d48358)', 'M-!U1^A^@^@^@^@4^O^@^@m^@^@^@s ^@^@^@^T^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@#^@^@^@s^@^@^@^T^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@...') ca lled at lib/Parrot/PackFile.pm line 206 Parrot::PackFile::unpack_filehandle('Parrot::PackFile=HASH(0x1d48358)', 'FileHandle=GLOB(0x1 d483e8)') called at lib/Parrot/PackFile.pm line 222 Parrot::PackFile::unpack_file('Parrot::PackFile=HASH(0x1d48358)', 'out.pbc') called at C:\pr ojects\parrot\parrot\disassemble.pl line 248 main::disassemble_file('out.pbc') called at C:\projects\parrot\parrot\disassemble.pl line 276
Parrot BASIC version .02, now with GAMES!
I'm well aware of the date, but this is no April Fool's Joke. (Well perhaps it is, but the joke would be on me.) A new version of BASIC can be found at http://geeksalad.org/basic This BASIC has a few interesting things over the last one. I/O now works (INPUT, LOAD, etc...) as well as interactive mode (a nice friendly Ready prompt). The expression parser is fully-functional now with functions, variable lookups, etc... There's a nice infix->postfix converter buried in there too. The programs "sample2" and "sample3" show off some of the language features. Best of all, if you can get it to load, Hunt the Wumpus in BASIC is now functional and playable. To get started, compile up a recent version of Parrot, and run the script "basic.pl" (it's just assembling the necessary pieces, handing off to assemble.pl, and running the result): Ready LOAD wumpus <-- type this Ready RUN<-- type this And you should be back in 1975 again. The only porting that had to be done for the code to work from David Ahl's original was to remove some DIM statements, change <> to !, and convert ON GOTO to a different structure. In other words: I'm done. :) I may add features later, but essentially it works. As Parrot gets better this will get more reliable. Speed will improve when I figure out -- and they get written -- some of Parrot's more sophisticated data structures like arrays. *** Notes for Parrot developers *** There's still string/stack/GC bugs in Parrot somewhere. In most cases, if the interpreter survives the LOAD process, then the BASIC program will run normally (and forever) without a hitch. Once loaded, BASIC tends to use and re-use the same space over and over again (thus, not allocating new memory). LOAD reads a file, splits the input buffer on \n, shoves lines onto the stack, and sorts the stack by line number. Sometimes Parrot does not survive this. The problem manifests itself as one of two errors: * LOAD triggers a SEGV * LOAD displays a spurious: LOADING sampleb.bas...Cannot take substr outside string (The error is probably legit, but it's because the input buffer is now trashed.) Curiously, re-arranging statements near the LOAD a bit causes the errors to go away and pop up elsewhere. Bummer.
Strings/Stack access hanging (small version)
>Try out bug #465 for size, as it's my current holdup (for some reason it >didn't forward to p6i). In this case a restore instruction sends the >parrot runtime into a loop from which it never (28 hours later) >recovers. It's probably Yet Another Garbage Collection bug or related to >the stuff that Melvin was working on, I dunno. > >Yes, the test case is HUGE but the rewards are great if it can be fixed. Now that my flu is abating, here's a small test case. Could someone please append this to bug #465's info as a preferred test case? It's probably even a fair test for parrot itself. If you want the DUMPSTACK routine, let me know otherwise just looking at the stack should be enough to tell that it went screwy. The hang occurs as you're re-reading the stack after this runs, one of the restore Sx instructions hangs. set I3, 0 set S3, "I am the very model of a moden major general I have information animal, vegetable a nd mineral." OUTER: set S0, S3 inc I3 set S1, "" eq I3, 10, END set I5, 0 LOOP: length I0, S0 le I0, 0, ENDLOOP substr S1, S0, 0, 5 sub I0, I0, 5 substr S0, S0, 5, I0 save S1 inc I5 branch LOOP ENDLOOP: branch OUTER END: save I5 #bsr DUMPSTACK # It hangs in here, the stack is already very corrupt # Ask if you need this. end
Re: "deep" tests for stacks.t
>Regardless, this patch does make 'make test' happy again, and should be >safe to apply apply, as long as we don't forget about the afore-mentioned >caveat, which will probably come back to bite us in the future if we don't >take care of it. I wonder how many more GC bugs are lurking, waiting for >good tests cases like these.. Try out bug #465 for size, as it's my current holdup (for some reason it didn't forward to p6i). In this case a restore instruction sends the parrot runtime into a loop from which it never (28 hours later) recovers. It's probably Yet Another Garbage Collection bug or related to the stuff that Melvin was working on, I dunno. Yes, the test case is HUGE but the rewards are great if it can be fixed.
Stack sorting
I took one of the smaller problems from the BASIC interpreter, sorting the stack, and posed it as a question on PerlMonks to see how a Mongolian Horde would handle the problem. The results are at: http://www.perlmonks.org/index.pl?node_id=153974 Summary: the only apparent way to do this trick is with a variation of a bubble sort (which I already had) given that there's only one user stack and three stack instructions (save, restore, rotate_up). A quicksort solution was posted, except that without being able to randomly address the stack it's nearly as bad as a bubblesort. The sorts presented there *were* more efficient than mine, so I'll probably borrow the technique eventually. Thought this might be of interest from a opcode-design standpoint. Enjoy.
Re: [FIX] Re: Some weekend fun: BASIC for Parrot
I just got this message and it's 1am. There's no way I'm applying patches this late. :) The situation I've got now works reasonably well using read/print. The version of BASIC I just uploaded to geeksalad.org/basic is okay unless you try performing a LOAD more than once with a reasonably large program like "sample.bas" -- then the input buffer becomes corrupted with apparently reclaimed memory. But if ya can get the data in, everything works *great*. Interactive mode's all working now, even a functonal INPUT statement. My TODO's are down to: 1. making sure this survives more Parrot "fixes" 2. making the expression evaluator understand "precedence" and 3. adding READ/DATA and a few functions RND, ASC, CHR$, MID$ and LEN.
Re: [FIX] Re: Some weekend fun: BASIC for Parrot
At 04:31 PM 3/23/2002 -0500, you wrote: >I've just fixed several bugs in the read ops, I commited so do a cvs update. >They were in the ops, not the IO system. Hasty coding is to blame, but I'm >glad someone is actually testing this now. > >I wrote a slurp test that reads in a file by line and concats each buffer >to the >main string, then prints the string out, with the following patch it works >ok, without it gets screwed up buffers. Okay. I've been unable to do a CVS update this afternoon, no response from the server during the checkout. But what I discovered was this: * Using print/read everything works fine. There is Joy. * Going anywhere near readline causes segvs * Using puts/read takes me back to the bad-old-days of garbage in my strings and stack from improper memory reclamation. I can't explain why, I only see the results. >>Second question: how do I use puts with a Ix register? That opcode >>doesn't seem to work... > >It doesn't use an Ix reg, it uses an PMC IO stream. If you want to print >to a stream use print PMC, STR on the PMC that open returned. No, no. I meant how do I output an Int or a Num to the output stream? Print's nice enough to allow me to say: print S0 print N0 print I0 And the Right Thing happens. Ah well, since I'm avoiding puts for the moment it's kind of a moot question.
Re: Some weekend fun: BASIC for Parrot
At 01:45 PM 3/23/2002 -0500, Melvin Smith wrote: >At 01:40 PM 3/23/2002 -0500, Melvin Smith wrote: >NEXTLINE: >> read S0, 256 >>-- print S0 >++ puts S0 >> branch NEXTLINE >> end > >Correction, print is stdio, puts is PIO. Use puts if you are using read. >I just checked it into CVS btw. You're suggesting that if I replace my 'print' with 'puts' everywhere that my I/O problems will vanish? Second question: how do I use puts with a Ix register? That opcode doesn't seem to work...
Some weekend fun: BASIC for Parrot
For your weekend entertainment, here's a bit of parrot assembler for the adventurous to play with. To get the code, just head to: http://geeksalad.org/basic and download the latest tar bundle you find. The README.basic file included in the tar bundle is listed after this. [Small amount of begging: someone please, please, please fix the I/O in Parrot! :)] DESCRIPTION --- This is the initial (.01?) release of a BASIC interpreter written entirely in Parrot bytecode. The NOTES below are intended for Parrot developers. This BASIC is of the fairly old school. Line numbers are required, and the following keywords are recognized: LIST LIST expr-expr RUN PRINT PRINT expr PRINT expr; [supress newline] DIM stringvar(expr) LET var=expr FOR var=expr TO expr FOR var=expr TO expr STEP expr GOSUB expr RETURN GOTO expr GO TO expr[syn with GOTO] IF expr conditional expr THEN STATEMENT END REM QUIT [exits interpreter] * String variables are noted with a trailing $ (as in A$) * Variable names are \w characters up to 8 in length (compile directive) * GOSUB/FOR-NEXT may be nested to arbitrary depths. * Line numbers are positive integers, up to 8-digits in length * Expressions are evaluated left-to-right with no thought given to precedence. They can be string literals or numeric with a mixture of operators (*+-/) and values. * Conditionals are >, <, =, or ! (not equal) * Everything is case-sensitive * Extra things on the end of a line are often ignored. This was intended as a true interactive BASIC (see NOTES below) so that any of the variables and statements work from the prompt as well as in the body of the stored program. Entering in a new line number overwrites the line in the existing program Included in this distribution are the following files, some of which may be of general interest, some only apply to BASIC: alpha.pasm Alpha/Numeric library dumpstack.pasm Diagnostic stack dumping expressions.pasmExpression evaluator stackops.pasm Stack operations tokenize.pasm A simple string tokenizer basic.pasm The instruction dispatcher basicvar.pasm Storage/Retrieval of BASIC strings, numbers, code instructions.pasm BASIC instructions test.basSmall BASIC example basic.plPerl Harness for compiling, starting BASIC in non-interactive mode (see NOTES). A small sample set of commands is embedded in the file. basic_io.pl Harness for compiling, starting BASIC in interactive mode (see NOTES). Not quite finished. The interactive mode isn't complete, and INPUT still needs to be implemented (see NOTES). Otherwise this should be fairly functional. NOTES - Parrot's I/O is really broken now. With all of the registers, stacks, and code involved here doing any kind of I/O breaks BASIC very quickly. As a self-contained program it's fairly robust. There's no INPUT statement (yet) and the interactive BASIC doesn't work. I'd really like both of these to work. It doesn't feel like BASIC without a friendly "Ok>" or "Ready" prompt. :) Included with the distribution is basic_io.pl which attempts to read instructions from STDIN (fd 0). If you can get this to work *consistently* with larger BASIC programs (i.e. lots and lots of I/O) let me know, I'd really appreciate it. Try: basic_io.pl < test.bas For a taste of SEGV. CONTACT --- Clinton Pierce <[EMAIL PROTECTED]> "clintp" irc.rhizomatic.net #perl or #parrot LICENSE --- Redistributable under the terms of any current version of Perl
Re: Problems with strings on the stack (small, concise example)
At 08:43 AM 3/22/2002 -0500, Bryan C. Warnock wrote: >On Friday 22 March 2002 08:22, Clinton A. Pierce wrote: > > Some patches committed last evening nearly took care of the problem -- at > > least they appeared to make my small example appear to > > work. Sometimes. :) Here's a slightly larger but better example that so > > far hasn't failed to show the stack corruption problem anywhere: > >Here's my output: > >Whammo 26> parrot clint2.pbc >one<-- save ( ;boundary) >two<-- save ( ;boundary) >three<-- save ( ;boundary) >four<-- save ( ;boundary) >five<-- save ( ;boundary) >six<-- save ( ;boundary) >seven<-- save ( ;boundary) >eight<-- save ( ;boundary) >nine<-- save ( ;boundary) >ten<-- save ( ;boundary) >eleven<--saved (endproc) No no. That's always fine. Now dump the stack. That's where the joy is! Stack Dump: (top to bottom) 0 Str eleven 1 Str ten 2 Str nine 3 Str eight 4 Str seven 5 Str six 6 Str five 7 Str n 8 Str 9 Str e 10 Str ;
Re: Problems with strings on the stack (small, concise example)
Some patches committed last evening nearly took care of the problem -- at least they appeared to make my small example appear to work. Sometimes. :) Here's a slightly larger but better example that so far hasn't failed to show the stack corruption problem anywhere: TOKENIZER: set S2, "one;two;three;four;five;six;seven;eight;nine;ten;eleven" set I5, 0# Stack pointer set S0, "" # Accumulating here TOKLOOP: length I0, S2 eq I0, 0, ENDTOK # Empty yet? substr S1, S2, 0, 1 # Peel off first character dec I0 substr S2, S2, 1, I0 eq S1, ";", SOMETHING # Break or append chars.. concat S0, S1 branch TOKLOOP SOMETHING: print S0 print "<-- save ( ;boundary)\n" savec S0 set S0, "" inc I5 branch TOKLOOP ENDTOK: length I0, S0 eq I0, 0, TOKBAIL inc I5 print S0 print "<--saved (endproc)\n" savec S0 TOKBAIL:save I5 #bsr DUMPSTACK end
Problems with strings on the stack (small, concise example)
(p6i cc'd) Okay, I've got this down to a dozen lines. I'm using a build pulled from CVS two hours ago. In case what's going on here isn't obvious, I'm shifting the first character off of S2 and putting it on the stack until S2 is finally exhausted. It's a boiled down version of my tokenizer. set S2, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" set I5, 0# Stack depth TOKLOOP: length I0, S2 eq I0, 0, DUMP substr S1, S2, 0, 1 dec I0 substr S2, S2, 1, I0 inc I5 savec S1 branch TOKLOOP DUMP: eq I5, 0, BAIL restore S0 print S0 dec I5 branch DUMP BAIL: end With the current build, even using your new savec opcode (or clone), the stack gets seriously messed up. [In this example, the save opcode doesn't have the problem! But in others it does. I can't get anything to behave consistently. Strings on the stack are just *broke*.] So for the code given, the output instead of appearing as: ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba You get the unlikely: ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjZYXWVUTSR (I think it only *appears* like the stack wrapped on itself, BTW. In larger examples, garbage from elsewhere seems to pollute the stack instead of earlier entries like this.) Dumping larger things on the stack makes the problem occur at shallower depths -- sometimes. It really seems like things that have been hanging around on the stack for a while get mashed. Sorry it took me so long to get this down to something concise. I wish it were smaller, not so critical to me, and a little more consistent.
Re: Various PASM routines
At 11:24 AM 3/19/2002 -0500, Dan Sugalski wrote: >At 11:15 AM -0500 3/19/02, Clinton A. Pierce wrote: >> >>What follows are a collection of PASM routines that I've been using while >>tinkering with the assembler and parrot. Feel free to use, mutilate, add >>to, discuss, mock. They are: > >These are cool, and thank you very much. Mind if I update these to match >the calling conventions when I get a chance? Actually, if I knew where to look I'd update them myself. :)
Various PASM routines
What follows are a collection of PASM routines that I've been using while tinkering with the assembler and parrot. Feel free to use, mutilate, add to, discuss, mock. They are: a tokenizer isalpha and isspace stack routines: sort, replace, peek, reverse a stack dump/display Many of the stack routines need a "magic" register set (I5) to indicate the depth of the stack, some do not. Where needed, it's indicated. This limitation will go away some day. Don't make fun of the sort, it works and is reasonable for small sorts. :) If you've got a better idea, patches welcome. There's probably a terribly clever way to sort a stack using only a couple of registers, push, pop, and rotate_up. I'm not that clever. As soon as the I/O routines are GC safe and readline() takes the correct arguments (doesn't play well with OPEN!) I might have some interesting code to show these off. I should probably fix the XML pseudo-Parser to use this improved tokenizer. Hrm.. Sample usage: set S10, "10 PRINT 'HELLO WORLD'" bsr TOKENIZER restore I5 bsr REVERSESTACK restore S1 # Line number dec I5# Stack depth counting. Grrr.. restore S2 # Keyword (print) dec I5 restore S3 # Arg ('hello world') dec i5 # etc... end [I'm not subscribed to p6i, but catch it in archives. CC [EMAIL PROTECTED] if it's important] # tokenizer # Input: string to be parsed on the stack (will be removed) # Output: stack contains number of tokens first, # then the tokens as seen right to left # Quotes (single or double) are *preserved* so that # Foo "bar hlaghalg" # is two tokens, and the second is "bar hlaghalg" # TOKENIZER: pushi pushs set I6, 0# Inquote set I7, 0# ALPHA restore S10 # String to tokenize set I5, 0# Stack pointer set S9, "" # Playground TOKLOOP: length I0, S10 eq I0, 0, ENDTOK substr S1, S10, 0, 1 dec I0 substr S10, S10, 1, I0 eq S1, "'", QUOTE eq S1, '"', QUOTE branch CKQUOTED QUOTE: ne I6, 0, EOTOK set I6, 1 set S9, S1 branch TOKLOOP EOTOK: set I6, 0 concat S9, S1 save S9 inc I5 set S9, "" branch TOKLOOP CKQUOTED: eq I6, 0, NOTQUOTED concat S9, S1 branch TOKLOOP NOTQUOTED: save S1 bsr ISWHITE restore I2 ne I2, 1, NOTSPACE # Spaces will end a token length I0, S9 eq I0, 0, TOKLOOP save S9 inc I5 set S9, "" branch TOKLOOP NOTSPACE: save S1 bsr ISALPHA restore I0 length I1, S9 ne I1, 0, NOTEMPTY set S9, S1 set I7, I0 branch TOKLOOP NOTEMPTY: ne I0, I7, TOKCHANGED concat S9, S1 branch TOKLOOP TOKCHANGED: save S9 inc I5 set S9, S1 set I7, I0 branch TOKLOOP ENDTOK: length I0, S9 eq I0, 0, TOKBAIL save S9 inc I5 TOKBAIL:save I5 popi pops ret # User Stack Dump (Debugging.) # ** I5 should contain the stack depth, # ** until I get some method of determining depth # Types # 1 is an int # 2 is a num # 3 is a string # 4 is a PMC DUMPSTACK: pushi pushn pushs pushp print "Stack Dump: (top to bottom)\n" set I0, I5 gt I5, 0, DUMPLOOP print " -empty-\n" branch DUMPEND DUMPLOOP: entrytype I1, 0 print " " sub I2, I5, I0 print I2 print " " ne I1, 1, DUMPNOTINT print "Int " restore I1 save I1 print I1 branch DUMPANOTHER DUMPNOTINT: ne I1, 2, DUMPNOTNUM print "Num " restore N0 save N0 print N0 branch DUMPANOTHER DUMPNOTNUM: ne I1, 3, DUMPNOTSTRING print "Str " restore S1 save S1 print S1 branch DUMPANOTHER DUMPNOTSTRING: ne I1, 4, DUMPERR print "PMC " restore P0 save P0 print P0 branch DUMPANOTHER DUMPANOTHER: print "\n" rotate_up I5 dec I0 eq I0, 0, DUMPEND branch DUMPLOOP DUMPEND: popi popn pops popp ret DUMPERR: print "UNKNOWN TYPE\n" end # Stack Library # This'll get a whole lot cleaner when I can tell the # depth of the stack automagically # peek -- return whatever string is on the stack # Inputs: the offset on the stack # Outputs: the string # Non-Destructive! # Does *not* test for bounds conditions PEEK: pushi restore I0 set I3, I0 inc I0 set I2 0 PLOOP: ge I2, I3, POL rotate_up I0 inc I2 branch PLOOP POL: restore
Re: Request for help in stack processing
At 04:28 PM 3/15/2002 -0500, Dan Sugalski wrote: >At 4:01 PM -0500 3/15/02, Clinton A. Pierce wrote: >>I'm in the midst of writing some routines to debug pasm code, and one of >>the things I dearly want is a "stack dump" routine. I can *almost* code >>this in pasm, except I'm missing one last component: a way to tell the >>depth of the stack without causing the runtime to bail. >> >>Any of the following would help: >> >>1. a rotate_up() that doesn't take an argument, instead the WHOLE stack >>rotates. >> >>2. an opcode that will tell me the stack depth >> >>3. A mod to rotate_up or entrytype that lets me start indexing from the >>*bottom* of the stack. >> >>4. some way of harmlessly catching the internal error "Stack Depth Wrong" >> >>[I'm not subscribed to p6i, cc me if you can otherwise I'll catch it in >>archives. Thanks.] > >#4 needs to go in when we put in exceptions. Other than that... which do >you want? They're all reasonable, and while I don't want to do all of >them, any one of #s 1-3 are fine. #3 is a can of worms best not opened, I think. #2 on CPU's that I'm familiar with is usually done by querying the stack pointer register. In parrotish: set I0, SP dec I0 set SP, I0 # For a pop-without-a-target-register kind of action. Dunno if that's the kind of design goal you're looking for. Seems a shame to use a whole opcode just for querying/setting the stack depth. But now that I think about it, this might be fun because then you can: set I0, SP # Stake in the ground save X save Y save Z etc... (bunch of processing) ne some_exception_condition, okay # Whoops, error. set SP, I0 # Go back to your stake branch exception_handler okay: (more processing) #1 seems the cleanest, because you don't have to add anything new except some parsing bits. But going through a deep stack would get loopy. :) Hopefully, other than things like stack dumps, it won't happen often. Sorry I'm so non-commital. I'm approaching this like a fun little CPU to play with, but am (purposefully) trying to avoid developing an agenda or inject design.
Request for help in stack processing
I'm in the midst of writing some routines to debug pasm code, and one of the things I dearly want is a "stack dump" routine. I can *almost* code this in pasm, except I'm missing one last component: a way to tell the depth of the stack without causing the runtime to bail. Any of the following would help: 1. a rotate_up() that doesn't take an argument, instead the WHOLE stack rotates. I could push a sentinel on the stack before rotating and stop when I get back to it. 2. an opcode that will tell me the stack depth, (like a mod to entrytype to let me know I've underflowed or something.) 3. A mod to rotate_up or entrytype that lets me start indexing from the *bottom* of the stack. Again, I could use a sentinel to know when to quit. 4. some way of harmlessly catching the internal error "Stack Depth Wrong" I'd like this stack dump to be unobtrusive, so I can continue processing after taking a snapshot of things. Suggestions? [I'm not subscribed to p6i, cc me if you can otherwise I'll catch it in archives. Thanks.]