Recent Changes - Search:

PmWiki

pmwiki.org

edit SideBar

TomWikipedia

wikipedia article for editing only

Phix is the open source?, self-hosted?, interpreted? and compiled? programming language? that emphasizes simplicity and programmer friendly error messages.

|| name || Phix ||
|| logo || [[File:Phixlogo32.png|Phix logo]]  ||
|| caption || Phix logo ||
|| paradigm || [[Imperative programming|Imperative, procedural]], [[object-oriented programming|object-oriented]] ||
|| released || {{Start date and age|2006}} ||
|| developer || Pete Lomax ||
|| latest release version || 0.8.2 ||
|| latest release date || {{Start date and age|2020|11|24}} ||
|| typing ||[[Type_system#Static_type_checking|static]], [[Type_system#Dynamic_type_checking_and_runtime_type_information|dynamic]], [[Strong and weak typing|strong]], [[Duck typing|duck]] ||
|| programming_language || [[Self-hosting_(compilers)|self-hosted]] ||
|| operating system || [[Microsoft Windows|Windows]], [[Linux]], [[#Hello world, GUI|Browser]] ||
|| genre || [[Interpreted language]] or [[compiled language]] ||
|| license || [[Open_Software_License|Open Software License 3.0]] / [[Academic_Free_License|Academic Free License 3.0]] ||
|| file_ext || .e, .ex, .exw, .edb ||
|| influenced by || [http://openeuphoria.org/ Euphoria] ||
|| website || {{URL|phix.x10.mx}} ||

History==

Phix was released in 2006 based on the Euphoria? programming language written by Robert Craig in 1993.

In 2013 Phix was re-written to replace the closed-source FASM? back-end with open-source inline assembly.

|| Version || Date || Key Features
|| 0.7.6 || Jul 2017 || try/catch,regex,json
|| 0.7.7 || Feb 2018 || ipc,serialise
|| 0.7.8 || Mar 2018 || zip
|| 0.7.9 || Apr 2018 || (maintenance release)
|| 0.8.0 || Apr 2019 || gmp,xml,sqlite
|| 0.8.1 || Mar 2020 || structs, classes
|| 0.8.2 || Nov 2020 || unit testing
|| 1.0   || mid-2021 || anticipated release

Overview==

Phix <ref name=softcat/> is designed to be simple, clear, and generic. The goal of Phix is to make writing programs, and then debugging easier.

Phix is a hybrid interpreter/compiler: <ref name=hybrid/>

  • As an interpreter
    • p hello.exw
    • Phix reads, parses, makes executable code, and then executes it (directly from memory)
  • As a compiler
    • p -c hello.exw
    • duplicates interpreting, and saves the executable code to a file
    • you can run the saved program at any time (and ship it, without need for Phix anymore)

The is no extra step of a virtual machine interpreting bytecode? as with Python?. While compiling, some additional optimizations may be found, so a compiled program may run faster than an interpreted program.

Phix extends the Euphoria tradition <ref name=linuxformat/> of "fast to read, fast to pickup and fast to run".

Design Features===

For new programmers:

<ref name=pGUI/>/IUP <ref name=IUP/>) out of the box.

  • The compiler? generates executable binary files directly without the need to install any other compiler or linker; re-compiles itself by typing p -cp`.
  • Compiler and run-time errors are made as human-readable as possible, and always include the offending source file name and line number.
  • The five primitive data types.
  • Explicitly tagged ends, such as if ... then ... end if catch mores errors and avoids problems like the dangling else?.
  • Strings are fully mutable with variable length slice substitution. Sequences can grow and shrink at will with no manual housekeeping.
  • Consistent operators such that & operator always concatenates, and the + operator always adds (unlike JavaScript

<ref name=jspo/>).

  • Lots of examples: PCAN

<ref name=PCAN/> online archive, 500 bundled demos, and over 1250 entries on Rosettacode<ref name=phixrosetta/>.

For experienced programmers:

  • Automatic garbage collection?; available even for manually allocated raw memory
  • Run-time checking for out-of-bounds subscripts, uninitialized variables, inappropriate types.
  • A debugger? provides single-stepping and the ability to enable/disable on selected blocks/files
  • Execution profiling?
  • The switch statement requires an explict fallthrough statement which avoids need for continuous break statements
  • A simple built-in database?

<ref name=database/>, and SQlite <ref name=SQLite/>, <ref name=pSQLite/> wrappers.

  • Components such as ipc

<ref name=ipc/>, json? <ref name=json/>, curl <ref name=curl/>, zip <ref name=zip/>, gmp< ref name=gmp/>, regular expressions <ref name=regex/>, sockets <ref name=sock/>, and unit testing <ref name=unit/>.

Data-Types==

Phix only needs five primitive data types?:

            ┌────────┐
          ┌─┤ object ├─┐        ✼ Five primitive data-types
          │ └────────┘ │
          │            │
        number     sequence
          │            │
        integer      string

      └──────────┬─────────┘
                 │              ✼ Write your own ''type''
                type              to limit permitted values

    └────────────┬───────────┘
              struct            ✼ Reference data-types
              class               provide dot-notation and OOP


 }}}

Phix has a novel view of data-types;
<ref name=novel/>
you can do anything with just five data-types. All values are objects, "a constituent that is acted upon," while a data-type "limits permitted values." That makes a Phix @@object@@ the ''unlimited'' data-type.

There are only two distinct data-types you must learn: number and sequence.
* An @@object@@ is any value: number or sequence
* A @@number@@ is an integer or a floating point numeric value
** An @@integer@@ is a whole number (in the range ±1,000,000,000 )
** An @@integer@@ is also a @@number@@
* A @@sequence@@ is a list of values, of any length, and of any nesting level.
** A @@string@@ corresponds to UTF8 encoding; a list of character or byte values
** A @@string@@ is also a @@sequence@@

A @@type@@ is a user defined data-type. It is used to declare variables and for type-checking values as programs execute.
Because it is programmable, you can add extra features beyond type-checking. For example, you could issue user created error messages.

The reference data-types, @@struct@@ and @@class@@, deliver dot notation and OOP behavior.

The complexity of memory allocation and de-allocation is hidden and handled automatically by reference counting.
The programmer only sees that data-types appear to be simple.



!! Symmetical Indexing==

The @@sequence@@ is fundamental to the simplicity of Phix. Phix uses 1-based indexing because:
* the first item is indexed is 1
* the last index n is equal to the length of the sequence
* numbering from the head @@1 ... n@@  is symmetrical to numbering from the tail @@-n ... -1@@
* when searching for an item, an index value of 0 means "item not found"
* a slice is inclusive from the first index to the last index
* there are no off-by-one complications as found with 0-based indexing

Sequences with mixed values and strings work the same; both sequences and strings are mutable.

There have been many debates
<ref name=io0ah/>
<ref name=jggd/>
<ref name=hisham/>
<ref name=luamis/>
about the use of 0-based compared to 1-based indexing.
Pointer based languages, and pointer arithmetic, as described by
<ref name=EWD831/>
by [[Edsger_W._Dijkstra|Edsger W. Dijkstra]], have their place.
Phix has no pointers and has no need for 0-based indexing.

{{{
-- is a line comment

// is also a line comment

//              1   2   3   4   5    -- index head to tail

sequence s = { 10, 20, 30, 40, 50 }

//             -5  -4  -3  -2  -1    -- index tail to head

// one item
    ? s[2]
    ? s[-4]
                -- output for both is:
    ----->  30

// slice of one item
    ? s[2..2]
    ? s[-4..-4]
                -- output for both is:
    -----> {30}

// inclusive slice
    ? s[2..4]
    ? s[-4..-2]
                -- output for both is:
    -----> {30,40,50}

// empty sequence
    ? s[3..2]
    ? s[-3..-4]
                -- output for both is:
    -----> {}

// insert
    s[3..2] = {99}
    ? s
    -----> {10,20,99,30,40,50}

// prepend and append
    s = { 10,20,30,40,50 }

    s[1..0] = {0}               -- prepend
    s[$+1..$] = {6}             -- append

    ? s
    -----> {0,10,20,99,30,40,50,6}

    s[0..-1] = {9999}           -- append

    ? s
    -----> {0,10,20,99,30,40,50,6,9999}

// delete
    s = { 10,20,30,40,50 }

    s[2..2] = {}        -- item deleted
    ? s
    -----> {10,30,40,50}

    s[2..3] = {}        -- slice deleted
    ? s
    -----> {10,50}

The virtual space between items 2 and 3 is indexed as s[3..2]; this is where you can insert one item, or splice (concatenate) a sequence. Assigning a slice to an empty sequence {} deletes that slice. Use $ as a shorthand for length(s). You may now use s[1..0] to prepend a value to the head of sequence, and s[$+1..$] or even s[0..-1] to append a value to the tail of a sequence.

In "What’s the big deal? 0 vs 1 based indexing" <ref name=ssj01/> Steven Sagaert provides a simple explanation (for Julia?):

 That’s exactly it.
 1-based indexing is actual indexing like in mathematics,
 while 0-based “indexing” isn’t indexing at all but pointer arithmetic.
 This comes from C where an array is just syntactic sugar for a pointer.

One-based indexing provides: intuitive and comprehensive operations not possible with 0-based indexing), and that work identically for sequences and strings.

Parameter passing==

All arguments are used as if they are passed as pass-by-value?. An integer is passed by value, whereas number|sequence|string are passed by reference with copy-on-write? semantics. This realises the performance benefits of pass-by-reference? but with the simple behaviour of pass-by-value.

function set55(sequence s)
   s[5][5] = 5
   return s
end function

sequence a,b

// Case I
a = repeat(repeat(0,5),5) -- a 5x5 matrix
? a
    --> {{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0}}

// Case II
b = a
? b
    --> {{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0}}

// Case III
b = set55(a)
? b
    --> {{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,5}}

In Case I, sequence a is item {0,0,0,0,0} and four pointers to this item. No un-needed duplication occurs.

In Case II, sequence b is a pointer to a. No copying occurs.

In Case III, sequence a is unaltered. The unchanged items of b (thats b[1..4]) still point to a and only b[5] is actually changed.

Here a and b end up looking quite different but in fact still share 80% of their (lowest-level) contents.

 <font color="#008080">function</font><font color="#000000"> set55</font><font color="#0000FF">(</font><font color="#004080">sequence</font><font color="#000000"> s</font><font color="#0000FF">)</font>
 <font color="#000000">   s</font><font color="#0000FF">[</font><font color="#000000">5</font><font color="#0000FF">][</font><font color="#000000">5</font><font color="#0000FF">] =</font><font color="#000000"> 5 </font>
 <font color="#008080">   return</font><font color="#000000"> s </font>
 <font color="#008080">end function</font>
 <font color="#C0C0C0"></font>
 <font color="#004080">sequence</font><font color="#000000"> a</font><font color="#0000FF"> =</font><font color="#7060A8"> repeat</font><font color="#0000FF">(</font><font color="#7060A8">repeat</font><font color="#800000">(</font><font color="#000000">0</font><font color="#0000FF">,</font><font color="#000000">5</font><font color="#800000">)</font><font color="#0000FF">,</font><font color="#000000">5</font><font color="#0000FF">),</font><font color="#000080"><i> -- a 5x5 matrix</i></font>
 <font color="#000000">         b</font><font color="#0000FF"> =</font><font color="#000000"> set55</font><font color="#0000FF">(</font><font color="#000000">a</font><font color="#0000FF">)</font>

Automatic PBR optimisation

It is idiomatic use a sequence as an argument to a function and then immediately assign the result back to that sequence:

function chop( sequence a )
    for i=1 to length(a) do
        a[i] = truncate(a[i])
    end for
    return a
end function

sequence a = { 1.1, 2.2, 3.3, 4.4, 5.5 }
a = chop(a)
? a
    --> { 1,2,3,4,5}

Here the compiler applies a special optimization to make the local variable undefined over the call, leaving the parameter with a refcount of 1 and therefore amenable to in-situ modification.

In general, when parameters are modified locally (within the routine), sequences and sub-sequences are implemented very efficiently, because of copy-on-write? semantics.

Reference types

In contrast dictionary, struct, and class instance parameters are more accurately described as pass-by-reference, similar to Java <ref name=javapbv/>:

class mytest
  public string s
end class

procedure change(mytest c, d)
  c = new({"c"})
  d.s = "d"
end procedure

mytest
    a = new({"a"}),
    b = new({"b"})
change(a,b)

? a.s --> "a"
? b.s --> "d"
  • The parameter c points to the argument a. The assignment of c to new(), disconnects it from the argument, making c an independent variable. Changes to c are not visible in a.
  • The parameter d points to the argument b; changes to d are visible in b.

The statement delete(c) within the change procedure would cause the destruction of c, which in turn, would cause a.s to be destroyed. References to a.s would then crash Phix.

Examples==

Line comments start with a double hyphen -- or a C-style // and continue to the end of line.

Block comments start with /* and finish with */.

Hello world, console====

puts(1, "Hello, World!\n")

<font color="#7060A8">puts</font><font color="#0000FF">(</font><font color="#000000">1</font><font color="#0000FF">,</font><font color="#008000"> "Hello, World!\n"</font><font color="#0000FF">)</font>

Hello world, GUI====

include pGUI.e
IupOpen()
IupShow(IupDialog(IupVbox({IupLabel("World!")},"MARGIN=90x20"),"TITLE=Hello"))
if platform()!=JS then
  IupMainLoop()
  IupClose()
end if
 <font color="#008080">include</font><font color="#000000"> pGUI.e</font>
 <font color="#5E005E">IupOpen</font><font color="#0000FF">()</font>
 <font color="#5E005E">IupShow</font><font color="#0000FF">(</font><font color="#5E005E">IupDialog</font><font color="#800000">(</font><font color="#5E005E">IupVbox</font><font color="#800080">(</font><font color="#008080">{</font><font color="#5E005E">IupLabel</font><font color="#000080">(</font><font color="#008000">"World!"</font><font color="#000080">)</font><font color="#008080">}</font><font color="#0000FF">,</font><font color="#008000">"MARGIN=90x20"</font><font color="#800080">)</font><font color="#0000FF">,</font><font color="#008000">"TITLE=Hello"</font><font color="#800000">)</font><font color="#0000FF">)</font>
 <font color="#008080">if</font><font color="#7060A8"> platform</font><font color="#0000FF">()!=</font><font color="#000000">JS</font><font color="#008080"> then</font>
 <font color="#5E005E">  IupMainLoop</font><font color="#0000FF">()</font>
 <font color="#5E005E">  IupClose</font><font color="#0000FF">()</font>
 <font color="#008080">end if</font>

<gallery widths="217px" heights="87px" mode=nolines> File:phix-hwwin.png|Windows desktop File:phix-hwlnx.png|Linux desktop </gallery>

Simple function====

include pGUI.e  -- for CD_DEG2RAD

function deg_to_rad(number deg)
    return deg*CD_DEG2RAD
end function
?deg_to_rad(180)        -- outputs 3.141592654
{} = deg_to_rad(360)    -- explict discard rqd
 <font color="#008080">include</font><font color="#000000"> pGUI.e </font><font color="#000080"><i> -- for CD_DEG2RAD</i></font>

 <font color="#008080">function</font><font color="#000000"> deg_to_rad</font><font color="#0000FF">(</font><font color="#000000">number deg</font><font color="#0000FF">)</font>
 <font color="#008080">    return</font><font color="#000000"> deg</font><font color="#0000FF">*</font><font color="#004600">CD_DEG2RAD</font>
 <font color="#008080">end function</font>
 <font color="#0000FF">?</font><font color="#000000">deg_to_rad</font><font color="#0000FF">(</font><font color="#000000">180</font><font color="#0000FF">)       </font><font color="#000080"><i> -- outputs 3.141592654</i></font>
 <font color="#0000FF">{} =</font><font color="#000000"> deg_to_rad</font><font color="#0000FF">(</font><font color="#000000">360</font><font color="#0000FF">)   </font><font color="#000080"><i> -- explict discard rqd</i></font>

User defined types====

type index(object x)
    return integer(x) and x>0
end type
index ndx = 5
ndx = -2    -- run-time error "type check failure, ndx is -2", plus source code file name and line number
 <font color="#008080">type</font><font color="#000000"> index</font><font color="#0000FF">(</font><font color="#004080">object</font><font color="#000000"> x</font><font color="#0000FF">)</font>
 <font color="#008080">    return</font><font color="#004080"> integer</font><font color="#0000FF">(</font><font color="#000000">x</font><font color="#0000FF">)</font><font color="#008080"> and</font><font color="#000000"> x</font><font color="#0000FF">></font><font color="#000000">0</font>
 <font color="#008080">end type</font>
 <font color="#000000">index ndx</font><font color="#0000FF"> =</font><font color="#000000"> 5</font>
 <font color="#000000">ndx</font><font color="#0000FF"> = -</font><font color="#000000">2   </font><font color="#000080"><i> -- run-time error "type check failure, ndx is -2", plus source code file name and line number</i></font>

User defined types are used primarily for validation and debugging purposes, rather than being fundamentally different to the five core builtin types.

String mutation

Strings and sequences have the same behavior. Strings are fully mutable, with variable length slice substitution:

string s = "food"  ?s   --> outputs "food"
s[2..3] = "e"      ?s   --> outputs "fed"
s[2..1] = "east"   ?s   --> outputs "feasted"
 <font color="#004080">string</font><font color="#000000"> s</font><font color="#0000FF"> =</font><font color="#008000"> "food" </font><font color="#0000FF"> ?</font><font color="#000000">s  </font><font color="#000080"><i> -- outputs "food"</i></font>
 <font color="#000000">s</font><font color="#0000FF">[</font><font color="#000000">2</font><font color="#0000FF">..</font><font color="#000000">3</font><font color="#0000FF">] =</font><font color="#008000"> "e"     </font><font color="#0000FF"> ?</font><font color="#000000">s  </font><font color="#000080"><i> -- outputs "fed"</i></font>
 <font color="#000000">s</font><font color="#0000FF">[</font><font color="#000000">2</font><font color="#0000FF">..</font><font color="#000000">1</font><font color="#0000FF">] =</font><font color="#008000"> "east"  </font><font color="#0000FF"> ?</font><font color="#000000">s  </font><font color="#000080"><i> -- outputs "feasted"</i></font>

Exception handling ====

try
   integer i = 1/0
   -- or, for example, throw("file in use")
catch e
   ?e[E_USER]
end try
puts(1,"still running...\n")
 <font color="#008080">try</font>
 <font color="#004080">   integer</font><font color="#000000"> i</font><font color="#0000FF"> =</font><font color="#000000"> 1</font><font color="#0000FF">/</font><font color="#000000">0</font>
 <font color="#000080"><i>   -- or, for example, throw("file in use")</i></font>
 <font color="#008080">catch</font><font color="#000000"> e</font>
 <font color="#0000FF">   ?</font><font color="#000000">e</font><font color="#0000FF">[</font><font color="#004600">E_USER</font><font color="#0000FF">]</font>
 <font color="#008080">end try</font>
 <font color="#7060A8">puts</font><font color="#0000FF">(</font><font color="#000000">1</font><font color="#0000FF">,</font><font color="#008000">"still running...\n"</font><font color="#0000FF">)</font>

Output:

 "attempt to divide by 0" -- or "file in use"
 still running...

Filtering====

function odd(integer a) return remainder(a,2)=1 end function
function even(integer a) return remainder(a,2)=0 end function

?filter(tagset(10),odd)     -- ==> {1,3,5,7,9}
?filter(tagset(10),even)    -- ==> {2,4,6,8,10}
 <font color="#008080">function</font><font color="#000000"> odd</font><font color="#0000FF">(</font><font color="#004080">integer</font><font color="#000000"> a</font><font color="#0000FF">)</font><font color="#008080"> return</font><font color="#7060A8"> remainder</font><font color="#0000FF">(</font><font color="#000000">a</font><font color="#0000FF">,</font><font color="#000000">2</font><font color="#0000FF">)=</font><font color="#000000">1</font><font color="#008080"> end function
 function</font><font color="#000000"> even</font><font color="#0000FF">(</font><font color="#004080">integer</font><font color="#000000"> a</font><font color="#0000FF">)</font><font color="#008080"> return</font><font color="#7060A8"> remainder</font><font color="#0000FF">(</font><font color="#000000">a</font><font color="#0000FF">,</font><font color="#000000">2</font><font color="#0000FF">)=</font><font color="#000000">0</font><font color="#008080"> end function
  
 </font><font color="#0000FF">?</font><font color="#5E005E">filter</font><font color="#0000FF">(</font><font color="#5E005E">tagset</font><font color="#800000">(</font><font color="#000000">10</font><font color="#800000">)</font><font color="#0000FF">,</font><font color="#000000">odd</font><font color="#0000FF">)    </font><font color="#000080"><i> -- ==> {1,3,5,7,9}
 </i></font><font color="#0000FF">?</font><font color="#5E005E">filter</font><font color="#0000FF">(</font><font color="#5E005E">tagset</font><font color="#800000">(</font><font color="#000000">10</font><font color="#800000">)</font><font color="#0000FF">,</font><font color="#000000">even</font><font color="#0000FF">)   </font><font color="#000080"><i> -- ==> {2,4,6,8,10}

</i></font>

Version control====

requires("0.8.2")           -- crashes on 0.8.1 and earlier
requires(WINDOWS)           -- crashes on Linux
requires(64)                -- crashes on 32-bit

Specify what versions and/or operating systems are required to run the source code:

 <font color="#5E005E">requires</font><font color="#0000FF">(</font><font color="#008000">"0.8.2"</font><font color="#0000FF">)          </font><font color="#000080"><i> -- crashes on 0.8.1 and earlier</i></font>
 <font color="#5E005E">requires</font><font color="#0000FF">(</font><font color="#004600">WINDOWS</font><font color="#0000FF">)          </font><font color="#000080"><i> -- crashes on Linux</i></font>
 <font color="#5E005E">requires</font><font color="#0000FF">(</font><font color="#000000">64</font><font color="#0000FF">)               </font><font color="#000080"><i> -- crashes on 32-bit</i></font>

In the latter case, if you try to run a 64-bit-only program with a 32-bit interpreter, it will try to locate a suitable 64-bit interpreter and offer to re-run it with that (and vice-versa, for instance the older arwen and win32lib libraries are 32-bit only).

Unit testing====

test_equal(2+2,4,"2+2 is not 4 !!!!")
test_summary()
 <font color="#5E005E">test_equal</font><font color="#0000FF">(</font><font color="#000000">2</font><font color="#0000FF">+</font><font color="#000000">2</font><font color="#0000FF">,</font><font color="#000000">4</font><font color="#0000FF">,</font><font color="#008000">"2+2 is not 4 !!!!"</font><font color="#0000FF">)</font>
 <font color="#5E005E">test_summary</font><font color="#0000FF">()</font>

If all goes well, no output is shown, and the program carries on normally.

You can easily force a summary to be output, quietly create a logfile, etc. <ref name=unit/>

Error reporting====

When a Phix program crashes, it produces a programmer-readable file, ex.err, which contains the full call stack and the value of every variable at that point. These can be quite large, but the most pertinent information is typically at the start of the file.

Error messages are made as clear as possible, for example

  C:\Program Files (x86)\Phix\demo\ilest.exw:43 in function strip_comments()
  type check failure, line is {"--","-- builtins/assert.e (an autoinclude)..

At that particular point line was supposed to be a string, not a list of strings.

Where possible the compiler tries to pre-empt that kind of run-time error with a compile-time error:

  C:\Program Files (x86)\Phix\demo\ilest.exw:43 in function strip_comments()
  line = 5
       ^ type error (storing atom in string)

Source level tracing====

Place with trace before any block of code you want to step through, and without trace before any block you want to skip

The program will then run until the condition (i=1234) is met, before single-stepping through the subsequent code.

Source level tracing in Phix?

Type based debugging====

Suppose some table t has the contents {12.35, 15.87, 17.17, ..} at some point of failure, but you were expecting t[3] to be 17.57.

It would normally be very helpful to know where exactly the wrong contents were placed in that table. Edit and re-run with say:

--sequence t = {}
type badtable(sequence t)
   if length(t)>=3 and t[3]<17.2 then
      ?9/0
   end if
   return true
end type
badtable t = {}
 <font color="#000080"><i>--sequence t = {}</i></font>
 <font color="#008080">type</font><font color="#000000"> badtable</font><font color="#0000FF">(</font><font color="#004080">sequence</font><font color="#000000"> t</font><font color="#0000FF">)</font>
 <font color="#008080">   if</font><font color="#7060A8"> length</font><font color="#0000FF">(</font><font color="#000000">t</font><font color="#0000FF">)>=</font><font color="#000000">3</font><font color="#008080"> and</font><font color="#000000"> t</font><font color="#0000FF">[</font><font color="#000000">3</font><font color="#0000FF">]<</font><font color="#000000">17.2</font><font color="#008080"> then</font>
 <font color="#0000FF">      ?</font><font color="#000000">9</font><font color="#0000FF">/</font><font color="#000000">0</font>
 <font color="#008080">   end if</font>
 <font color="#008080">   return</font><font color="#004600"> true</font>
 <font color="#008080">end type</font>
 <font color="#000000">badtable t</font><font color="#0000FF"> = {}</font>

That will crash at the required point, producing an ex.err, alternatively you could trace(1) to start source-level tracing instead.

Note that without typecheck directives in the source code can completely disable this technique.

Feature summary==

Paradigms: imperative, procedural, optionally object-oriented

Standardized: No, the manual includes the language specification

Type strength: strong

Type safety: safe

Expression of types: explicit, partially implicit

Type compatibility: duck

Type checking: dynamic, static

Parameter Passing Methods Available: copy on write, immutable reference, multiple returns

Garbage collection: Reference counting

Intended use: Application, Educational, General, High-level scripting, Text processing

Design goals: Simplicity, Readability, Ease of use

Unsupported features==

Phix does not (although most can be emulated) directly support operator/builtin/function overloading, lambda expressions, closures, currying, eval, partial function application, function composition, function prototyping, monads, generators, anonymous recursion, the Y combinator, aspect oriented programming, interfaces, delegates, first class environments, implicit type conversion (of the destructive kind), interactive programming, inverted syntax, list comprehensions, metaprogramming, pointers (other than to raw allocated memory), topic variables, enforced singletons, safe mode, s-expressions, or formal proof construction. The author wryly comments "That should both scare off and attract the right people"

No operator overloading? means that + always adds values.

No function overloading? refers to there being at most one (polymorphic) version of a routine in a given scope

A simple and compact language is not limiting. Phix has some 1,277 <ref name=phixrosetta/> completed Rosettacode <ref name=rosetta/> tasks (second <ref name=phixsecond/> only to Go?).

Criticism==

The inline assembly on which Phix is based is x86/64 only, making an ARM port extremely difficult.

The extensive run-time checking, which can increase productivity, incurs an inevitable performance penalty (at times a factor of 8), Type-checking can be reduced with the without typecheck statement, but not eliminated completely.

Floating point operations typically incur additional indirection and/or memory allocation cSompared to other languages.

The use of inline assembly to alleviate runtime hotspots is both difficult to understand and poorly documented.

Comparable languages==

References==

External links==

Languages implemented in Phix==

{{DEFAULTSORT:Phix (programming language)}} :Category:Procedural programming languages? :Category:Cross-platform software? :Category:Programming languages created in 2006? :Category:Free educational software?

Edit - History - Print - Recent Changes - Search
Page last modified on February 10, 2021, at 11:59 AM