User:Petelomax/sandbox

Phix is an open source, self-hosted, interpreted or compiled programming language with a strong emphasis on simplicity and plain human-readable error messages.

History
Robert Craig released the first version of Euphoria in July 1993. In 2006, Pete Lomax created Phix as a clone of Euphoria, initialy relying on a closed-source backend written in FASM. By 2013 the backend had been transferred to (open-source) inline assembly, which removed that dependency completely.

Versions 0.8.0/1/2 have been retrospectively nominated 1.0.0/1/2, though the binaries and documentation retain the above numbers. The next release will be 1.0.3, expected mid-2021.

Overview
The design of Phix is based on four tenets: simplicity, clarity, consistency, and making debugging easier, rather than clinging to the vain hope of avoiding it altogether.


 * The five core data types can be remembered on the fingers (and thumb) of one hand, see below.
 * Phix implements automatic garbage collection, even for manually allocated raw memory, albeit the latter is optional and defaults to false.
 * Programs can be interpreted or compiled. Interpretation is fast as it builds the same machine code as compilation, just executes it directly in memory.
 * Compilation of a program you've been interpreting is as simple as adding a -c switch, eg 'p test' --> 'p -c test': command lines are kept dirt simple.
 * Compiler and run-time errors are made as human-readable as possible, and always include the offending source file name and line number.
 * Incorporates both a source-level debugger with single-stepping and the ability to enable/disable on selected blocks/files, and an execution profiler.
 * Strings are fully mutable with variable length slice substitution. Sequences can grow and shrink at will with no manual housekeeping.
 * Extensive run-time checking occurs for out-of-bounds subscripts, uninitialized variables, inappropriate types (eg trying to store a string in an integer), etc.
 * The switch statement requires an explict fallthrough statement when that is desired, rather than punishing an accidentally omitted break statement.
 * Does not natively have the kind of "maths" whereby 255 plus 1 is 0, 0-1 is +4GB, or 127+1 is -128, although such is achievable via and_bits [gmp rqd for > 32 bits].
 * Consistent operators, eg the Phix & operator always concatenates, and the + operator always adds, unlike say JavaScript.
 * Explicitly tagged ends, such as "if ... then ... end if", while more verbose than {}, catch more errors and avoid problems such as the dangling else.
 * The Windows installation includes a complete graphical user interface (pGUI /IUP ) out of the box, though some additional setup is required on Linux.
 * Work is in progress, on a new wrapper for GTK (est completion Q1 2022), and several older (usually 32-bit only) wrappers exist.
 * Phix has a simple built-in database and SQlite, , and wrappers for a variety of other databases.
 * Components such as ipc, json , curl , zip , gmp , regular expressions , sockets , and unit testing are also bundled in with Phix (currently 30MB).
 * An archive of some 2000 other user contributions is available online, as well as about 500 bundled demos and over 1250 entries on rosettacode.
 * The compiler generates executable binary files directly without the need to install any other compiler or linker.
 * To re-compile Phix from source simply run `p -cp`. No other compilers or similar tools need to be installed.
 * Available for Windows and Linux, in both 32 and 64 bit versions.
 * Work on a Transpiler to JavaScript is in progress (est completion Q3 2021), so that programs can be run in a browser.

Five core types
Phix has just five builtin data types: < object -> |               |        +-number         +-sequence |               |          +-integer        +-string

• An object can hold any value, specifically either a number or a sequence. • A number (aka atom) can hold a single floating point numeric value, or an integer. • An integer can hold a single whole number (at least +/- 1,000,000,000). • A sequence can hold a collection of values, of any length, nested to any depth, or a string • A string can hold a series of characters, or raw binary data, and is fully mutable.

The underlying memory allocation and deallocation is handled automatically via reference counting.

Note that in Phix the term 'object' has no special relationship to object-orientated programming.

Further user-defined types can also be defined, for instance dictionaries and class instances, however they are actually just specialised versions of the above.

The number type has recently been added as an alias of the traditional but less intuitive atom, and will not be available until 1.0.3 is shipped.

1-based indexes
The widespread use of 0-based indexes stems from a paper by Edsger W. Dijkstra and the benefits for pointer arithmetic, which Phix does not have. There have been many other debates   about the use of 0-based vs. 1-based indexing. In 0-based indexing the first,last,length are 0,n-1,n whereas in 1-based indexing they are 1,n,n. If the first element of an array is a[0], you cannot index the last as a[-0], whereas a[1] and a[-1] are much more reasonable.

In a language with both 0-based indices and negative indices, apart from the above disjoin, there is no sensible value that eg find can return that is a non-functional index, whereas in Phix, find can return 0 and that won't accidentally retrieve the wrong element. In Phix, s[5..5] has a length of 1, and s[5..4] a length of 0, whereas in Python s[5:5] has a length of 0, it is s[5:6] that has a length of 1. You don't need to explain 1-based indexing to anyone and you certainly don't need a diagram. For these reasons, Phix uses 1-based indexing, similar to Julia and Lua.

In "What’s the big deal? 0 vs 1 based indexing" 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 allows extensive and intuitive operations on sequences.

Core types
Integers are always passed by value, whereas number/sequence/string are passed by reference with copy-on-write semantics. That realises the performance benefits of pass-by-reference but with the behaviour of pass-by-value, for example:

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

The value of a is not changed by the call, b obviously ends up with a single 5 in the lower right. In fact it only "clones" the top-level of b and b[5], b[1..4] actually still share the same memory as a, but will cease doing that if and when further modifications are made to b. It will not need to re-clone the top-level of b or b[5] again (and now ditto a) but can instead update those non-shared parts in situ. The fact that non-integer numbers quiely undergo a similar treatment should be of little or no practical concern, expect perhaps to note that an additional indirection and/or memory allocation is often associated with floating point operations.

Automatic PBR optimisation
When a local variable is both passed as an argument to a routine and explicitly reassigned on return, the compiler applies a special optimisation by which the local variable becomes undefined over the call, leaving the parameter with a refcount of 1 and therefore amenable to in-situ modification. Even when this does not occur, all parameters can be modified locally (i.e., within the callee) which is implemented very efficiently as sequences (and sub-sequences) have automatic copy-on-write semantics. In other words, when a sequence is passed to a routine, initially only a reference to it is passed, but at the point it is modified the very minimum necessary internal cloning is automatically performed and the routine only updates the now-uniquely-owned parts, leaving the original intact, albeit with some reduced hidden reference counts. In the above, a and b end up looking quite different but in fact still share 80% of their (lowest-level) contents.

Reference types
In contrast, dictionary and struct/class instance parameters are more accurately described as pass-by-reference. Again the reality is slightly different, similar to Java, for example:

<font color="#008080">class <font color="#000000"> mytest <font color="#008080"> public <font color="#004080"> string <font color="#000000"> s  <font color="#008080">end class <font color="#C0C0C0"> <font color="#008080">procedure <font color="#000000"> change <font color="#0000FF">( <font color="#000000">mytest c <font color="#0000FF">, <font color="#000000"> d <font color="#0000FF">) <font color="#000000"> c <font color="#0000FF"> = <font color="#5E005E"> new <font color="#0000FF">( <font color="#800000">{ <font color="#008000">"c" <font color="#800000">} <font color="#0000FF">) <font color="#000000"> d <font color="#0000FF">. <font color="#000000">s <font color="#0000FF"> = <font color="#008000"> "d" <font color="#008080">end procedure <font color="#C0C0C0"> <font color="#000000">mytest a <font color="#0000FF"> = <font color="#5E005E"> new <font color="#0000FF">( <font color="#800000">{ <font color="#008000">"a" <font color="#800000">} <font color="#0000FF">), <font color="#000000">      b <font color="#0000FF"> = <font color="#5E005E"> new <font color="#0000FF">( <font color="#800000">{ <font color="#008000">"b" <font color="#800000">} <font color="#0000FF">) <font color="#000000">change <font color="#0000FF">( <font color="#000000">a <font color="#0000FF">, <font color="#000000">b <font color="#0000FF">) ? <font color="#000000">a <font color="#0000FF">. <font color="#000000">s <font color="#000080"> -- "a" <font color="#0000FF">? <font color="#000000">b <font color="#0000FF">. <font color="#000000">s <font color="#000080"> -- "d"

In practice, a remains unmodified, because we simply overwrote the reference to it, whereas b is modified indirectly as and when the field of d is updated. Note that had you instead performed delete(c), then a would have instantly become meaningless and invalid, and further that a cannot be nullified within change other than by making it a function which returns (c or null), and then explicitly assigning that return back to a (and you might then want to make class mytest nullable).

One other (fairly obvious) true thing to say is that new creates space to hold values, and you can never hold more values, that is, in instance variables, than the number of times you have invoked new. A very similar program but with no classes and all strings could at one point hold four different strings in a,b,c,d, but that is simply not possible in the above because new has only been called three times.

Examples
Line comments start with a double hyphen  or a C-style   and continue to the end of line. Block comments start with  or   and end with   or , and can be nested. Euphoria treats the -- style as a line comment, which is why two types exist.

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

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

Note the browser screenshot is from a close-ish proof-of-concept, rather than actual output from the currently in progress transpiler (est Q3 2021).

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

User defined types
<font color="#008080">type <font color="#000000"> index <font color="#0000FF">( <font color="#004080">object <font color="#000000"> x <font color="#0000FF">) <font color="#008080">   return <font color="#004080"> integer <font color="#0000FF">( <font color="#000000">x <font color="#0000FF">) <font color="#008080"> and <font color="#000000"> x <font color="#0000FF">&gt; <font color="#000000">0 <font color="#008080">end type <font color="#000000">index ndx <font color="#0000FF"> = <font color="#000000"> 5 <font color="#000000">ndx <font color="#0000FF"> = - <font color="#000000">2  <font color="#000080"> -- run-time error "type check failure, ndx is -2", plus source code file name and line number Note that 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 are fully mutable, with variable length slice substitution: <font color="#004080">string <font color="#000000"> s <font color="#0000FF"> = <font color="#008000"> "food" <font color="#0000FF"> ? <font color="#000000">s <font color="#000080"> -- outputs "food" <font color="#000000">s <font color="#0000FF">[ <font color="#000000">2 <font color="#0000FF">.. <font color="#000000">3 <font color="#0000FF">] = <font color="#008000"> "e"    <font color="#0000FF"> ? <font color="#000000">s <font color="#000080"> -- outputs "fed" <font color="#000000">s <font color="#0000FF">[ <font color="#000000">2 <font color="#0000FF">.. <font color="#000000">1 <font color="#0000FF">] = <font color="#008000"> "east" <font color="#0000FF"> ? <font color="#000000">s <font color="#000080"> -- outputs "feasted"

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

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

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

Version control
Specify what versions and/or operating systems are required to run the source code: <font color="#5E005E">requires <font color="#0000FF">( <font color="#008000">"0.8.2" <font color="#0000FF">)         <font color="#000080"> -- crashes on 0.8.1 and earlier <font color="#5E005E">requires <font color="#0000FF">( <font color="#004600">WINDOWS <font color="#0000FF">)         <font color="#000080"> -- crashes on Linux <font color="#5E005E">requires <font color="#0000FF">( <font color="#000000">64 <font color="#0000FF">)              <font color="#000080"> -- crashes on 32-bit 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
<font color="#5E005E">test_equal <font color="#0000FF">( <font color="#000000">2 <font color="#0000FF">+ <font color="#000000">2 <font color="#0000FF">, <font color="#000000">4 <font color="#0000FF">, <font color="#008000">"2+2 is not 4 !!!!" <font color="#0000FF">) <font color="#5E005E">test_summary <font color="#0000FF"> 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.

Debugging
Phix takes the pragmatic view that debugging is inevitable and essential and should be as user-friendly as possible. In short, Phix strives to provide an intuitive version of the features you never knew gdb had.

Error reporting
When a Phix program crashes, it produces a human-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, of course, the compiler tries to pre-empt that kind of run-time error with a compile-time error, eg

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 section(s) of code you want to step through, and "without trace" before any you want to skip (which can be an entire block of include statements, typically there is not much point single-stepping through any of the tried-and-tested standard includes that are pre-installed with Phix) and something like "if i=1234 then trace(1) end if" at some appropriate point.

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



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:

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

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, fairly obviously, 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 does what you think it should. No builtin overloading means that min always does what the manual says, not (sometimes) extract the 36 out of "2:36:15pm". No function overloading refers to there being at most one (polymorphic) version of a routine in a given scope, not ten from which compiler picks, using convoluted argument type matching rules. Other entries in that list, in particular eval and interactive programming, may be nice-to-haves and are not necessarily ruled out forever.

Despite, or perhaps because of that, Phix has some 1,277 completed rosettacode tasks, second only to Go

Notable failures and criticism
If Phix were written in C it would be more portable is a common criticism. The author points to Euphoria and the problems compiling that as a rebuttal.

The inline assembly on which Phix is based is x86/64 only, making (for instance) an ARM port extremely difficult (there are an estimated 24,000 lines of such code).

For many years Phix would consistently segfault (preventing all use) on some versions of Linux but not others. This is now believed to have been caused by kernels that require 16(as opposed to 8)-byte stack alignment. A source-level patch is available for 0.8.2 (aka 1.0.2), but 1.0.3 will be the first binary release with that fix pre-applied, and several others,.

While Phix claims to be an all-in-one installation, and comes with IUP binaries pre-installed on Windows, it is necessary to install IUP and/or GTK on Linux manually before a GUI can be used. The instructions for installing IUP on Linux in particular are somewhat hidden (demo/pGUI/lnx/installation.txt) and of generally poor quality.

System-wide installation such that Phix can be run from any directory is poorly documented on all systems.

The Edita editor (windows 32-bit only, bundled with Phix), hangs on startup if there are any non-responsive windows. Another attempt to fix this is promised for 1.0.3.

Installation on windows defaults to C:\Program Files (x86)\Phix\ however unless that directory is granted full access permissions (and Phix reinstalled), the VirtualStore aka File and Registry Virtualization feature of windows is known to cause problems. Those problems would (probably) be solved if the installation process made proper use of %ALLUSERSPROFILE% and %LOCALAPPDATA% as it should.

The natural syntax of say person.age is actually mapped by the compiler front-end to (eg) structs:fetch_field(person, "age"). No similar mapping is performed for dictionaries, which must use eg setd("key", "value", mydict) style syntax, rather than say mydict["key"] := "value".

The extensive run-time checking, which can increase productivity, incurs an inevitable performance penalty (at times a factor of 8), but while eg "without typecheck" helps, it cannot generally be fully disabled.

Subscript performance in particular, while substantially faster than say Python or JavaScript, is substantially slower than say C%2B%2B or Go (mainly for the reason just mentioned).

Floating point operations typically incur additional indirection and/or memory allocation compared to other languages (the impact of which is usually less noticeable than subscripts).

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

The phix debugger does not support reverse or replay debugging.

Many programmers weaned on 0-based indexing will find the transition to 1-based indexing rather painful, at least at first.

Comparable languages

 * Euphoria
 * Lua
 * Go
 * Python
 * JavaScript
 * Julia
 * REBOL
 * Ruby

Comparison with Euphoria
The following differences were present in the first release: Over the last 14 years the implementation of Phix has slowly diverged from Euphoria as follows:
 * Phix has 8-bit strings and variable length slice substitution
 * Phix requires explicit sequence ops such as sq_add rather than an implicit inline +
 * Euphoria requires equal and compare in many cases where Phix allows ==, <, etc.
 * Euphoria can be transpiled to C, Phix cannot
 * Euphoria allows floating-point for loop control variables, Phix does not
 * Euphoria requires explict includes for many things Phix can auto-include
 * The machine_func/machine_proc of Euphoria are mostly deprecated in Phix
 * Phix has structs and classes, with reference semantics
 * What Euphoria calls maps, Phix calls dictionaries, and uses a different syntax
 * Phix has multithreading, as well as multitasking, whereas Euphoria only has the latter
 * Phix allows negative indexes from right to left, mirroring positive indexes' left to right
 * Phix has named parameters, and does not permit parameter omission with ,, syntax
 * Phix allows the explicit := and == as well as the (implicit) = determined from context
 * Phix allows nested constant declarations via the := operator
 * Euphoria does not support the ~ << >> && || operators
 * Phix allows ; as an entirely optional statement separator
 * Euphoria allows full expressions in parameter defaults whereas Phix is relatively limited
 * Euphoria returns a length of 1 for an atom, whereas Phix (deliberately) crashes
 * Euphoria requires routine_id("name") whereas Phix also allows a bare name
 * Euphoria requires call_func(rid,{...}) whereas Phix also allows rid(...)
 * Phix allows inline variable declaration in desequencing operations
 * Phix has a format directive to specify compilation options, nothing of that ilk in Euphora
 * The ternary operator (iff) in Phix has full short-circuit evaluation, not so in Euphoria
 * Phix allows forward routine declarations and un-named parameters
 * Euphoria supports binary/octal/hex/decimal, Phix supports all number bases 2..36
 * Phix allows static variables and routine-level constants (except on fwd calls)
 * Euphoria supports enum by /N, which Phix does not
 * Euphoria's private/export/global are all simply treated as global by Phix
 * Several include and with/without options are different and/or incompatible
 * Euphoria namespaces can reference the current file, which is broken in Phix
 * Euphoria allows forward references to variables, Phix does not
 * Euphoria allows implicit discard of function results, Phix requires "{} ="
 * Euphoria has with label, break label, and a loop construct, Phix does not
 * Phix has a try/catch/throw, whereas Euphoria has no exception handling
 * Phix allows min(i,j) as well as min({i,j,k,..}), ditto max
 * Euphoria still has match_from whereas Phix relies on match optional start
 * Euphoria yields 97.36 for lower(65.36) whereas Phix yields 65.36
 * Euphoria permits daisy-chaining delete_routine, Phix is single-shot
 * Euphoria must allocate_string for c_func, Phix can pass strings directly
 * Phix has number as an alias for atom, Euphoria does not
 * Phix supports inline assembly (and sometimes relies on it)
 * No new version of Euphoria has been released since Feb 2015

Despite all these, a fair amount of legacy code still runs happily on both.

Languages implemented in Phix

 * Phixmonti and Klingphix (spanish) see also Phixmonti and Klingphix on rosettacode

Category:Procedural programming languages Category:Cross-platform software Category:Programming languages created in 2006 Category:Free educational software