PEU - The Portable Euphoria Interpreter Project

August 26,1999

August 4, 1999
In response to something Rob said on the listserv...


> 2) In the documentation it states a "string" is simply a
> sequence of numbers. Does this mean each character
> takes 4-bytes of memory, or does Euphoria store them in
> single bytes until it has some compelling reason to do
> otherwise?

They take 4 bytes. This has been discussed before.
It would be nice if they could only take one byte, and
I've spent a good deal of time looking for a convenient
way to do this. Unfortunately, any 1-byte scheme
seems to have the following disadvantages:

    * It makes the interpreter bigger, thereby wasting
       some of the space you are trying to save.
Yeah, whatever... adding to the interpreter will be a *fixed* amount, while saving 75% on every single character sequence.

    * It makes the interpreter a few percent slower.
Yes, but it will not have to internally convert the 4-byte chars into 1-byte chars before poking them into memory or passing to a c-function.

    * It makes the interpreter more susceptible to bugs.
    * It makes the interpreter harder to maintain
That's for absolutely certain! Just look at Peu... it does byte-sized sequences and is quite unstable.

June 18,1999. Not much has been going on with Peu... the version on my hard drive is now at 0.12.2, and works with Allegro, XwinAllegro, Win32, and regular console versions. Binding is a mess, some things work, most things don't. With RDS Euphoria for Linux looming over the horizon, perhaps I should get in gear and finish the last core parts of the interpreter and throw up some binaries for people to play with. I've also got a lot of compiler knowledge from CS480 and want to make a simple Euphoria compiler written in Euphoria, possibly co-developed by David Cuny.

Nov 16,1998. Whiles loops implemented... speed is twice as fast as the old peu, but still can't hold a candle to ex.exe. Added, the ability to initialize variables at declaration... the first departure from "conventional" Euphoria syntax. Other things I would like to add are: exception handling, forward proc/func calls, += operators, etc.

Nov 7,1998. Version 0.11: supported so far: constants, variable declarations, sequence creation, the repeat function, integer addition, the "?" command, the time() function. PEU now interprets code as it parses, in the same way as ex.exe, so constants are calculated and replaced inline, and constant expressions will be folded into a single value. Speed seems to just slightly under par with respect to ex.exe, probably due to an unoptimized parser. I'd like to see how my new bytecode scheme compares inside a loop though.

Nov 1, 1998. Well, work has once again begun on peu.c... I've got some great ideas that I've been dying to code. Though I do hate it when inspiration strikes at 4am... I'm doing a total rewrite of the function-pointer engine, no more evil type-casting ints into things they're not supposed to be. That should help on systems that have >32-bit pointers. Built-in functions will be stored as a special type of object, so they can be used in an expression with no need for a data stack. Variables will be used in a similar way. Allegrophoria will still be supported, and a X-window implementation will be investigated. Mac is questionable, though. Unix implementations will probably need a terminal.e file for fancier text, with vt100 escape codes or something. More info to come...


Inspired by David Cuny's Project X, I have also begun work on a Euphoria interpreter that can be ported to other platforms. This requires conforming to the ANSI C spec, so this new Euphoria should run on any platform having an ANSI C compiler. I am currently using the DJGPP compiler for DOS, and the GNU C compiler for Unix. The current version of the interpreter compiles and runs identically on both systems. In order to keep the incentive to register RDS' Euphoria, PEU error messages give as little information as possible. No line number, no variable names, no function name, no ex.err file, no traceback, just a plain "your program is bad"-type message.

Added July 30: the ability to declare and assign to variables. The four basic types are supported: object, sequence, atom and integer. Two built-in functions have been added: length and repeat. The types also have their associated function.

Added July 31: string and character literals and files, puts, putc, getc, and print. The maximum of file numbers open at one time is limited only by your OS, because the interpreter stores the FILE*'s internally as a sequence :)

Later July 31: append, prepend, &

August 1: type-checking for variables, fixed negative integer bomb, and cleaned up the code a little.

August 2: open, close, include, with/without whatever, sequence slicing and subscripting, assigning to a subscripted variable...

August 3: fixed assignments to subscripted variables, added assignments to sliced variables

August 6: while/end while loops. Functions: or_bits, and_bits, xor_bits, compare. Operators: +, -, *, /, =, !=, <, <=, >, >=, or, and.

August 8: if/elsif/else/end if, unary -, not.

August 9: rand, set_rand

August 10: not_bits

August 11: procedure/end procedure, function/end function, type/end type, (recursivity confirmed), return, for/end for. Arguments to procedures/functions/types are type_checked, if type_check is on.

August 13: hopefully eliminated "out of addressing space" messages. renamed get_env --> getenv.

August 14+: wrappers for Allegro...

August 17: exit, system, command_line

August 19: Monty King has contributed a FLI player for Allegrophoria. You can get venus.fli from the Euphoria Archives.

August 20: Here's a wave file demo by Monty. And a midi demo by me. The allegro wrappers are finished.

August end: Squashed some bugs. Added sort. Discovered strip.exe (not what you think) resulting in smaller executables.

Sept. 1: PEU still barfs when compiled with LCC, Watcom, Borland and CygWin32. I think it's a good time to do a major rewrite of the core code. All that bad casting is gonna get canned. Millions of peaches, peaches for me. Millions of peaches, peaches for free. Lookout!

Download version 0.10 (August 31):
source and executable 78k
source only 17k
Allegrophoria source only 62k
Allegrophoria executable only 286k
Compiling requires a 32-bit ANSI compiler. Running the executable requires DPMI services, such as Windows or CWSDPMI.EXE. Compiling Allegrophoria requires DJGPP and the Allegro 3.0 Game Toolkit.

To compile PEU, type something like "gcc peu.c -o peu.exe" or "gcc peu.c -o peu" for Unix. On some Unix systems, executable files must reside in a 'bin' directory.

Way-old output:

PEU - Porta-Euphoria (stinky version)

integer a
a = 1
while a do
? a
a = 0
end while
sequence s
s = {1, 2, 3, 4, 5, 6, 7, 8}
? s
while length(s) do
s = s[2..length(s)]
? s
end while
? 0 = ({1, 2, 0, 0, 0, 6} = {1, 2, 3, 4, 5, 6})

[RUN]
1
{1,2,3,4,5,6,7,8}
{2,3,4,5,6,7,8}
{3,4,5,6,7,8}
{4,5,6,7,8}
{5,6,7,8}
{6,7,8}
{7,8}
{8}
{}
{0,0,1,1,1,0}

This output shows a bug I just fixed in the append function. The sequence became self-recursive when "foo[1] = foo". Which wasn't a problem... until you tried to print it :)

PEU - Porta-Euphoria (stinky version)

sequence foo, bar
foo = repeat(1.1, 3)
bar = foo
? foo
foo = prepend(foo, foo)
? foo
foo = append(foo, foo)
? foo
foo[1] = foo
? foo
? bar

[RUN]
{1.1,1.1,1.1}
{{1.1,1.1,1.1},1.1,1.1,1.1}
{{1.1,1.1,1.1},1.1,1.1,1.1,{{1.1,1.1,1.1},1.1,1.1,1.1}}
{{{1.1,1.1,1.1},1.1,1.1,1.1,{{1.1,1.1,1.1},1.1,1.1,1.1}},1.1,1.1,1.1,{{1.1,1.1,1
.1},1.1,1.1,1.1}}
{1.1,1.1,1.1}
sequences_created = 5, sequences_destroyed = 5
doubles_created  = 14, doubles_destroyed  = 14

Here's another output dump:

PEU - Pete's Euphoria Interpreter

? repeat({}, 5)
? "Test"
? 'A'
puts(1, repeat('x', 10))
putc(1, '\n')
puts(1, "Hello Euphorians!\n")
puts(1, "Hello Euphorians! ")
putc(1, 49)
putc(1, 50)
putc(1, 51)
putc(1, 52)

[RUN]
{{},{},{},{},{}}
{84,101,115,116}
65
xxxxxxxxxx
Hello Euphorians!
Hello Euphorians! 1234

Here is one which allocates a fairly big sequence:

PEU - Pete's Euphoria Interpreter

integer x
x = 1
? integer(x)
? integer(1)
? atom(1)
? atom(1.5)
? sequence({})
? sequence(x)
? sequence(1.5)
? integer({})
? integer(1.5)
? atom({})
? length({})
? length(repeat(0, 4000000))

[RUN]
1
1
1
1
1
0
0
0
0
0
0
4000000

The parser is in debug mode on in these outputs, so the source code is displayed as it is translated before it is run.

Here is some sample output from a previous version.

PEU - Pete's Euphoria Interpreter

global constant a = 1,
b = 2.5e-10,
s = {1, #2AB, 5}
? a
? {a, b}
? {5, a, {1, 2, 3, 4}}
? 1
? {s}
? {s, s, s, {s, s}}
? {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
[RUN]
1
{1,2.5e-10}
{5,1,{1,2,3,4}}
1
{{1,683,5}}
{{1,683,5},{1,683,5},{1,683,5},{{1,683,5},{1,683,5}}}
{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}