Russian Korean French Thai
euphoria

The Euphoria Programming Language 3.1.1

Contents

1. What is Euphoria?

Euphoria is a simple, flexible, and easy-to-learn programming language. It lets you quickly and easily develop programs for Windows, DOS, Linux and FreeBSD. Euphoria was developed and first released in 1993 by Robert Craig. Since then Rapid Deployment Software has been steadily improving it with the help of a growing number of enthusiastic users. Although Euphoria provides subscript checking, uninitialized variable checking and numerous other run-time checks, it is extremely fast. People use it to develop Windows GUI programs, high-speed DOS games, and Linux/FreeBSD X Windows programs. It is also very useful for CGI (Web-based) programming.

1.1 Tutorial - Hello World!

with trace
trace(1)

-- Tutorial - Print Hello World on the Screen

-- To run this tutorial,
--        Press Enter to execute the highlighted Euphoria statement.
--        Press F1 to flip to the main output screen.
--        Press F2 to flip back to this trace screen.
--        Read the comments as you go.

-- Step 1: Just to be neat - we'll clear the screen.
-- First, press F1 then F2 (Works best on DOS or DOSBox).
-- Then press Enter:
clear_screen()
-- Check again with F1/F2 - was the screen cleared?

-- Step 2: Let's position the cursor at line 10, column 30
position(10, 30)
-- Is the cursor now at 10,30? Press F1/F2

-- Step 3: Display the text:
puts(1, "Hello World")
-- Is the text there? Press F1/F2

-- Step 4 Output 2 blank lines and we're done
puts(1, "\n\n")

1.2 Example Program

The following is an example of a complete Euphoria program (Try it online!).
sequence list, sorted_list

function merge_sort(sequence x)
-- put x into ascending order using a recursive merge sort
    integer n, mid
    sequence merged, a, b

    n = length(x)
    if n = 0 or n = 1 then
	return x  -- trivial case
    end if

    mid = floor(n/2)
    a = merge_sort(x[1..mid])       -- sort first half of x
    b = merge_sort(x[mid+1..n])     -- sort second half of x

    -- merge the two sorted halves into one
    merged = {}
    while length(a) > 0 and length(b) > 0 do
	if compare(a[1], b[1]) < 0 then
	    merged = append(merged, a[1])
	    a = a[2..length(a)]
	else
	    merged = append(merged, b[1])
	    b = b[2..length(b)]
	end if
    end while
    return merged & a & b  -- merged data plus leftovers
end function

procedure print_sorted_list()
-- generate sorted_list from list
    list = {9, 10, 3, 1, 4, 5, 8, 7, 6, 2}
    sorted_list = merge_sort(list)
    ? sorted_list
end procedure

print_sorted_list()     -- this command starts the program

The above example contains 4 separate commands that are processed in order. The first declares two variables: list and sorted_list to be sequences (flexible arrays). The second defines a function merge_sort(). The third defines a procedure print_sorted_list(). The final command calls procedure print_sorted_list().

The output from the program will be:
 {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}.

merge_sort() will just as easily sort {1.5, -9, 1e6, 100} or {"oranges", "apples", "bananas"} .

This example is stored as euphoria\tutorial\example.ex. This is not the fastest way to sort in Euphoria. Go to the euphoria\demo directory and type "ex allsorts" to see timings on several different sorting algorithms for increasing numbers of objects. For a quick tutorial example of Euphoria programming see euphoria\demo\bench\filesort.ex.

2. Download Euphoria (32-bit)

Checksum
Euphoria Release Notes
Read Me
How to Install Euphoria on Windows
How to Install Euphoria on Linux or FreeBSD
How to run Euphoria on 64-bit Linux
How to run Euphoria on 64-bit (& 32-bit) FreeBSD
Euphoria Reference Manual Part I - Core Language


Note: all .doc files are actually simple ASCII .txt files.

3. Download Lib2 for Euphoria

Lib2 is an extended standard library for the Euphoria Programming Language version 3.1, with lots of useful functions.

Lib2 includes also the edu IDE with context sensitive help (control-K), syntax coloring and more.

Checksum
Lib2 Release Notes

4. Utilities and Demo Programs

Checksum

5. Tips

  1. How to name variables properly?
    I can only suggest that you name variables in a consistent and self-explanatory way, but not too lengthy, like this:
    • constants - using capital letters only, e.g.: CONFIG_1, PI, etc
    • global variables - start by a capital letter and prefix, e.g.: Cfg_colors, Cfg_defaults, Ed_colors, Ed_defaults, etc
    • local variables - use only small letters, e.g.: mem_address, etc
    • private variables - use only small letters and short names, e.g.: mem, s, etc
    In general, don't use global and local scopes unless you have to. There is a big advantage for private scope, it is called: modularity.
    Moreover, for private scope to be clear, limit your subroutines to a reasonable size - a short subroutine is much easier to understand and maintain.
    Avoid using long variable names - you're not writing a novel.
  2. How to do integer division in Euphoria 3?
    Use the builtin floor() function for fast integer division, for example (Try it online!):
    -- use floor() to do integer division where needed (it's faster):
    constant CYCLES = 1000000
    integer r
    
    constant T = time()
    
    for i = 1 to CYCLES do
        r = 4 + floor(100 / 7) * 2
    --  r = 4 + 100 / 7 * 2     -- non-integer (atom) division is slower
    end for
    
    ? time() - T -- print time measurement
        
  3. How to use the 'global' scope in a controlled manner?
    Declare your global variables and include files in your startup file, for example:
    -- how to declare your *global* variables, constants, or anything else
    -- in your main startup file - it's all depends on the order, For example:
    
    -- 1) Euphoria/Lib2 include files are declared first, so they don't
    --    have any access to your global variables or include files
    include graphics.e
    include misc.e
    
    -- 2) this global block is visible by all include files below,
    --    i.e. config.e and editor.e
    global sequence app_config
    include config.e
    
    -- 3) this global block is visible only by editor.e file (module)
    global constant EDITOR_COLORS = {WHITE, BLACK, CYAN, BLACK, BRIGHT_WHITE}
    global integer editor_mode, exit_editor
    include editor.e
    
    -- *) run main program loop. ('exit_editor' is only visible to editor.e).
    while exit_editor = 0 do
        editor()
    end while
    
    -- declaring your include files *only* in your startup file, together with
    -- your global variables can be a good programming technique.
        
  4. Using a single-dimension sequence vs. multi-dimension sequence:
    Unless you really need a multi-dimension sequence, a single-dimension sequence is always faster and much easier to use (but less "cool" I know). This is also true for an array in other programming languages. For example:
    -- a multi-dimension sequence is slower and harder to use, for example:
    sequence key_value
    
    constant KEY_INDEX = 1, VAL_INDEX = 2
    
    key_value = {
        {"Shian", "Eric", "Joe"},
        {{3, 4}, {93, 1}, {'x', 40}}
    }
    
    ? key_value[KEY_INDEX][3]
    ? key_value[VAL_INDEX][3][2]
    
    -- a single-dimension sequence is *faster* and *easier* to use, for example:
    sequence key, value
    
    key = {"Shian", "Eric", "Joe"}
    value = {{3, 4}, {93, 1}, {'x', 40}}
    
    ? key[3]
    ? value[3][2]
    
    -- note: inside a loop you may want to use a variable for even faster access:
    sequence s
    
    s = key[3]
    
    for i = 1 to 100 do
        puts(1, s)  -- direct access to variable without an index-overhead
    end for
        
    Yet, a multi-dimension sequence is still more practical for many cases, for example: the dir() function returns a multi-dimension sequence rightfully, and high-speed is not important in this case.
  5. Using compact code vs. regular code:
    -- 'compact' code in Euphoria 3 is very short and may run much
    -- faster then 'regular' code, but *not* always.
    --
    -- From the following test of the lower() function (convert atom
    -- or sequence to lower case), we learn that:
    --  1. "regular" code is the slowest (but simple).
    --  2. "compact" code is very short, stable, and very fast *only*
    --      if *all* elements of object x must be manipulated.
    --  3. "fast" code (optimized regular code) is very long but fast.
    --  4. "string" code is the fastest, but limited to string-sequence
    --      only (the other routines can manipulate *any* object).
    --
    -- This test is just an example for specific problem. Each case may
    -- behave differently. The file math.e in Lib2, for example, is
    -- using a lot of "compact" code, which makes the code much *shorter*
    -- and probably *faster* in many cases.
    
    
    constant TO_LOWER = 'a' - 'A'
    
    -- 'regular' code, simple, longer, and slower:
    function regular_lower(object x)
        if atom(x) then
    	if x >= 'A' and x <= 'Z' then
    	    return x + TO_LOWER
    	end if
        else -- sequence(x)
    	for i = 1 to length(x) do
    	    x[i] = regular_lower(x[i]) -- recursive call
    	end for
        end if
        return x
    end function
    
    -- 'compact' code, very short, stable, and may be very fast:
    function compact_lower(object x)
        return x + (x >= 'A' and x <= 'Z') * TO_LOWER
    end function
    
    -- 'fast' code, highly optimized regular code, very long, but faster:
    function fast_lower(object x)
        sequence s -- accessing sequence s is a bit faster then accessing object x
    
        if atom(x) then
    	if x <= 'Z' then
    	    if x >= 'A' then
    		return x + TO_LOWER
    	    end if
    	end if
    	return x
        end if
    
        -- sequence(x)
        s = x
        for i = 1 to length(s) do
    	if atom(s[i]) then
    	    if s[i] <= 'Z' then
    		if s[i] >= 'A' then
    		    s[i] += TO_LOWER
    		end if
    	    end if
    	else -- sequence(s[i])
    	    s[i] = fast_lower(s[i]) -- recursive call
    	end if
        end for
        return s
    end function
    
    -- 'string' code is very fast, but useful *only* for a string-sequence:
    function string_lower(sequence s)
        for i = 1 to length(s) do
    	if s[i] <= 'Z' then
    	    if s[i] >= 'A' then
    		s[i] += TO_LOWER
    	    end if
    	end if
        end for
        return s
    end function
    
    
    -- now, let's test the speed of each routine, using 3 strings:
    
    constant CYCLES = 500000
    sequence r, s, names, strings
    atom t, t2
    integer id
    
    -- routine names:
    names = {"regular_lower", "compact_lower", "fast_lower", "string_lower"}
    
    -- test strings:
    strings = {"RAPIDEUPHORIA", "RaPidEuphOriA", "rapideuphoria"}
    
    for test = 1 to length(strings) do -- test different strings
        s = strings[test]
        puts(1, s & "\n\n")
    
        for routine = 1 to length(names) do -- test different routines
    	id = routine_id(names[routine])
    
    	t = time()
    	for i = 1 to CYCLES do
    	    r = call_func(id, {s})
    	end for
    	t2 = time() - t
    
    	printf(1, "%15s: %5.2f\n", {names[routine], t2}) -- print result in sec
        end for
    
        puts(1, "\n\n")
    end for
        

5.1 DOS and Qemu

  1. How to create a bootable FreeDOS USB stick & Euphoria 3?
    I've created a raw image (2GB size) of FreeDOS 1.2.
    The image also includes Euphoria 3.1.1, Lib2 1.41, RBIL documentation, helppc, QE 2.3.9 IDE, EDU IDE (as part of Lib2), and basic utilities.

    When you start FreeDOS it will run a menu written in Euphoria 3 (you can see the source code in C:\UTIL\MENU.EX).

    Just download the compressed image (checksum), decompress it using 7-zip, burn it to a USB stick of 4GB or more, and restart your computer from the USB stick. (Legacy BIOS must be enabled in your BIOS, and you should be able to start your computer from USB-HDD).

    In Linux you can burn the image using the attached documentation, or another Linux utility. On Windows you can (probably) use Rufus to burn the image to a USB stick.

    -----------------------------------------------
    How did I make this image on Linux?
    -----------------------------------------------

    Using qemu-system-x86_64 --version QEMU emulator version 2.0.0 (Debian 2.0.0+dfsg-2ubuntu1.46), Copyright (c) 2003-2008 Fabrice Bellard.
    1. Download "FD12CD.iso" from http://www.freedos.org/.
    2. Create an empty local Disk as file, using 'dd':
      dd if=/dev/zero of=fdos12.img bs=1M count=2047
    3. Install "FD12CD.iso" to Disk, using 'qemu':
      qemu-system-x86_64 -cdrom FD12CD.iso fdos12.img -boot d
      Notes:
      1. In FDISK I did NOT enable large drive support on start.
      2. I created a single 2GB drive C: (2GB is maximum for standard DOS drive), made it bootable, then restart qemu with ctrl-alt-del... then continue with format and minimal installation.
    4. Copy from another FreeDOS USB stick the Euphoria directory & other utilities and documents, using 'qemu' (/dev/sdb1 is my USB device):
      sudo qemu-system-x86_64 -hdb /dev/sdb fdos12.img
    5. Test again if the image is bootable, using 'qemu':
      qemu-system-x86_64 fdos12.img -boot c
    6. Burn the bootable image to a USB stick, using 'dd':
      sudo dd if=fdos12.img of=/dev/sdb bs=1M
    7. Test the new USB stick, using 'qemu':
      First find the USB id, using 'lsusb':

      lsusb
      = ( Bus 002 Device 005: ID 0781:5567 SanDisk Corp. Cruzer Blade )
      Now test it using ID 0781:5567:
      sudo qemu-system-x86_64 -usb -usbdevice host:0781:5567 -m 1024 -vga std
      (Using the above qemu command FreeDOS runs OK from the USB stick!)
    8. OK. Ready. Now you can reboot your PC from the USB stick (legacy BIOS must be enabled in the BIOS)... and you can start using FreeDOS and Euphoria!
  2. Example batch files for running DOS in Qemu:

    I'm using this batch file to run "fdos12.img" on Linux:
    #!/bin/bash
    #
    # File name: dos.sh
    #
    # I'm Using qemu-system-x86_64 --version:
    # QEMU emulator version 4.2.0 (On Linux Debian 1:4.2-3ubuntu6.4)
    # ==============================================================
    #
    # When you start qemu:
    # --------------------
    # Press control-alt-f to toggle full screen mode
    # Press control-alt-g to (toggle) grab the keyboard & mouse into DOS
    # Press control-alt-0 or control-alt-minus or control-alt-plus to zoom best-fit/out/in
    #
    # To share files with a FAT-16 or FAT-32 (DOS) formatted USB stick, append
    # also the following command (change "/dev/sdb" if needed to your USB stick path):
    # --------------------------------------------------------------------------------
    #
    #    -drive file="/dev/sdb",format=raw,if=ide,media=disk
    #
    # Note that you should run qemu as root to access the USB drive, i.e.:
    # sudo qemu-system-x86_64 ... if using USB stick, then make sure the USB stick
    # is not mounted in Linux, and do NOT remove it until you exit Qemu.
    
    qemu-system-x86_64	`# qemu version 4.2.0` \
        -drive file="fdos12.img",format=raw,if=ide,media=disk	`# is a disk to add to DOS` \
        -boot order=c	`# tells qemu which disk to boot from (in order)` \
        -m 1024	`# memory to use (1024=1GB; Euphoria runs in protected mode so it's useful)` \
        -k en-us	`# keyboard (English-US is the standard keyboard)` \
        -rtc base=localtime	`# the clock` \
        -soundhw sb16,adlib,pcspk	`# sound hardware to emulate (sb16,adlib,pcspk are common for DOS programs)` \
        -vga std	`# type of screen (standard VGA)` \
        -no-quit	`# disable the [x] on title bar` \
        -name "FreeDOS 1.2"	`# text for qemu's title bar`
    	
    I'm using this batch file to run "fdos12.img" on Windows-10:
    @ECHO OFF
    REM File name: DOS.BAT
    REM
    REM I'm Using qemu-system-x86_64 --version
    REM QEMU emulator version 5.1.0 (v5.1.0-11824-g8699890d91-dirty)
    REM On Windows-10 64-bit
    REM ==============================================================
    REM
    REM When you start qemu:
    REM --------------------
    REM Press control-alt-f to toggle full screen mode
    REM Press control-alt-g to (toggle) grab the keyboard & mouse into DOS
    REM Press control-alt-0 or control-alt-minus or control-alt-plus to zoom best-fit/out/in
    REM
    REM To share files with a FAT-16 or FAT-32 (DOS) formatted USB stick, append
    REM also the following command (change "/dev/sdb" if needed to your USB stick path):
    REM --------------------------------------------------------------------------------
    REM
    REM    -drive file="/dev/sdb",format=raw,if=ide,media=disk
    REM
    REM Note: if using USB stick, then do NOT remove it until you exit Qemu.
    REM
    REM You can also specify old PC speaker <name>: -machine pcspk-audiodev=<name>
    REM
    REM Remember to set path for Qemu (Once per session):
    REM     "SET PATH=C:\Program Files\qemu;%PATH%"
    REM - or set the path permanently in Windows-10's settings (environment variables).
    REM
    
    qemu-system-x86_64 -drive file="fdos12.img",format=raw,if=ide,media=disk -boot order=c -m 1024 -k en-us -rtc base=localtime -device adlib -device sb16 -vga std -no-quit -name "FreeDOS 1.2"
    
    REM Short description:
    REM -drive a disk to add to DOS.
    REM -boot tells qemu which disk to boot from (in order).
    REM -m memory to use (1024=1GB since Euphoria 3 runs in protected mode it's useful).
    REM -k keyboard (English-US is the standard keyboard)
    REM -rtc the clock
    REM -device adlib -device sb16 sound hardware to emulate (sb16,adlib,pcspk are common for DOS programs).
    REM -vga type of screen (standard VGA)
    REM -no-quit disable the [x] on qemu's title bar
    REM -name title bar text of qemu
    
    	
    Some Qemu links:

7. About

shian
  • Name: Shian.
  • Education: By Shlomo Kalo.
  • Faith: God's Love.
  • Quote: “I am the way, the truth, and the life. No one comes to the Father except through Me." - John 14:6, the New Testament.
  • Quote 2: “Martha, Martha, you are worried and troubled about many things. 42 But one thing is needed, and Mary has chosen that good part, which will not be taken away from her.” - Luke 10:41, the New Testament.
  • Contact: s h i a n @ r a p i d e u p h o r i a 3 1 1 . c o m