Falcon (programming language)
From Seo Wiki - Search Engine Optimization and Programming Languages
Round Falcon logo
|Usual file extensions||.ftd, .fal|
|Paradigm||multi-paradigm: procedural, object-oriented, prototype-based, functional, tabular, message passing|
|Designed by||Giancarlo Niccolai|
|Stable release||0.9.6 (Chimera) (2010-01-11)|
|Preview release||0.9.1.8 (Crane RC2) (2009-05-20)|
|Influenced by||C++, Perl, Lua, Smalltalk, PHP, Lisp, Python, Ruby|
|License||GPLv2, FPLLv1.1 (a modified version of the Apache License)|
Falcon translates computer source code to virtual machine instructions for evaluation. The virtual machine is thought both as a stand-alone interpreter and for integration in third party embedding applications.
A core design consideration for the Falcon Programming Language is to provide acceptably high performing scripting extensions to multi threaded data acquisition, reporting and dispersion applications. Work continues towards that end as Falcon approaches an official 1.0 reference implementation. Doxygen processed source code posted at falconpl.org.
As programming languages go, Falcon design leans more towards conciseness of code and expressiveness than general readability. The Falcon implementation does provide facilities for source level documentation and this documentation may become important as the mixed paradigm potential of Falcon scripting attempts to meet the problems faced with programming in the large.
A small project, HASTE, developed in 2002, in an attempt to create a small fast virtual machine, soon evolved into the Falcon Programming Language. In early 2008, the package was first shipped under open source licensing as a package in Ubuntu, and included in the KDE 4 scripting framework.
Rather than focusing on one programming style or paradigm, Falcon merges several different styles into a single framework. At the same time, it targets multiple application domains (stand-alone, embedded into other applications and server-side dynamic pages), merging them into a single hood of a common architectural design.
At the implementation level, Falcon is driven by the concept of service, where the scripting engine is seen as a service for scripts, modules and in embedded applications when not used as a stand-alone tool.
"Hello World" example
Although there are various forms of basic I/O, an example Hello world program using fast print:
> "Hello World!"
// International class; name and street class 国際( なまえ, Straße ) // set class name and street address नाम = なまえ شَارِع = Straße // Say who am I! function 言え() >@"I am $(self.नाम) from ",self.شَارِع end end // all the people of the world! 民族 = [ 国際( "高田 Friederich", "台湾" ), 国際( "Smith Σωκράτης", "Cantù" ), 国際( "Stanisław Lec", "południow" ) ] for garçon in 民族: garçon.言え()
which, when evaluated, displays
I am 高田 Friederich from 台湾 I am Smith Σωκράτης from Cantù I am Stanisław Lec from południow
- Nil - The nil keyword, a non-value.
- Integer - an integer 64 bit value.
- Numeric - An IEEE 64 bit floating point value.
- Range - a triplet of lower bound, higher bound and step.
- MemBuf - Raw memory buffer, where each location is an unsigned 1, 2, 3, or 4 bytes integer.
- Function - Functions (callable entities).
- String - Mutable sequences of UNICODE characters (but they can be used as byte buffers).
- Array - Mutable sequences of items.
- Dictionary - Mutable ordered set of key/value pairs; the key can be any Falcon item.
- Object - Instances derived from classes or stand-alone classless objects.
- Class - Classes, entities that can create instances.
- Method - Immutable pairs of instances and functions to be applied on them.
Falcon merges six major programming paradigms.
Procedural programming is supported through classic function declarations and calls. Every function supports implicitly variable parameter calls and named/positional parameters. A set of procedural style statements (as i.e. for, while, if, switch statements) is provided.
The following is a complete procedural program.
function sayList( saying ) for elem in saying >> elem formiddle: >> " " forlast: > "!" end end sayList( List("Have", "a", "nice", "day") )
Falcon has an evaluation engine called Sigma-reductor, which allows programmers to write pure functional programs, not differently from what is seen in Lisp. The intermixed programming style allows use of different paradigms (such as OOP or procedural approaches) in functional sequences, or to use functional evaluations during the course of otherwise procedural programs.
Functional sequences are represented by standard language arrays; this means that sequences can be created, inspected and changed dynamically by the program itself, either across different evaluations or during the course of a Sigma-reduction evaluation. The following example does that by changing a special variable reference, called late binding in a list loop.
seq = [ printl, '"', &value, '"' ] dolist( function(p); seq.value = p; eval(seq); end, ["Have", "a", "nice", "day"] )
Standard arrays can be called as functions if their first member is itself a callable item, as in the following example.
f = [printl, "Prompt> "] f( "Real data to print" )
One-level functional sequences (as in the above example) can be conceptually treated as cached calls, and once assigned to a variable, they are morphologically equivalent to a function symbol.
The functional paradigm includes an out of band item marker. Items can receive an oob flag marker which can be tested through language operators and functions and indicate a special meaning for values traveling in functional sequences. For example, many functional loops, as floop and times can perform loop restarts or can be interrupted by returning either a out of band 1 or 0 from any of the involved functions. The map function, transforming all the values in an array through a mapping function, will ignore the returned value (discarding it) if it's an out of band nil; in this way, it is possible to perform map-and-filter operations in place.
The Falcon Programming Language provides an OOP paradigm with classes, an inheritance model, class-static members, property initializers and instance constructor. Multiple inheritance is supported under the condition that at most one underling ancestor class is reflecting native data. Access to base class members is supported.
Instance structure is fixed and immutable, but due to Falcon functional nature where functions are seen as just a special kind of data, it is possible to set instance members to plain data or functions (making them methods) dynamically. Functional sequences can be assigned to properties, in which case they become functional methods for the given OOP instance.
Falcon supports stand-alone objects, which can be either classless or derived by class ancestors, which are instantiated and readied before the Virtual Machine executes the main script. Instance Resolution order is tracked by the Falcon Linker to ensure proper initialization of stand-alone objects, which may refer one another in program modules.
Class instances can be created through functional sequences, as instancing a class is morphologically equivalent to calling its symbol, and so, evaluating a functional sequence whose first element is a class has the effect of creating an instance.
Falcon OOP model is completed by operator overloading, which allows to create classes on which the mathematical and logical operators have a special behavior.
Prototype OOP is similar to OOP, but it drops the concept of classes. Instances are all classless, and their structure can be dynamically changed. Falcon language dictionaries (ordered key/value pair collections) can include functions; dictionaries can then be blessed to inform the language that they are to be treated as classless instances, and applying dot accessor causes their values to be treated as properties or methods. In the following example, a dictionary becomes an object:
dict = bless([ 'state' => 0, 'incme' => function(); self.state++; end ]) dict.incme() > dict.state // will print '1'
Bindings in arrays works similarly.
array = [1,2,3] array.showMe = function() for item in self > item end end array.showMe()
Message-oriented programming allows indirect calls to one or more registered listeners when a message is broadcast. The contents of the message are arbitrary and can include any language item, including but not limited to classes from which to create instances, functional sequences or tables. Listeners can either compete to receive the message and exclude the others, or participate in building a common reply to the message in ordered steps. Messages can be broadcast and require an immediate reply or can be left in the environment to be received and processed by latecomers (termed assertions in Falcon).
Message oriented programming has a direct interface into the Virtual Machine, on which external native modules and embedding applications can interact. For example, a multithreaded application may throw into the virtual machine messages coming from different threads, for serialized processing at script level and later broadcast of processed solutions directly from within the scripts.
Tabular programming can be seen as a special extension of OOP programming, where a class is represented by a table, whose columns are properties and where each row is an instance. Other than keeping all the instances together, and allowing each instance to work on the surrounding rows of the parent table, modification on the table are dynamically reflected into every instance.
Tables offer a means to select behaviors between a finite set of choices, or to mix behaviors and merge them, providing fuzzy logic engines. As each row, actually a Falcon array, can contain both table-specific data and logic or private logic (via array bindings), an entity selected in a table via global selection logic can provide specialized working abilities.
Along with the multiple paradigms, Falcon presents a variety of different features for programmers.
Base types and classes exposing the sequence interface to the internal engine offer a "comp" method which offers all the functionality of a list comprehension construct. The comp method takes a mandatory "source" parameter, which can be another sequence, an item of range type or a generator function returning one item at a time, and a special marker at termination.
A function (or in general a callable item) can be provided as second optional parameter, and acts both as a filter and modifier.
Associative pair sequences (as i.e. dictionaries) are supported as well.
The following is a simple example using a range to create a list comprehension; the result is an array of even numbers 2..10:
even_array = .comp( [2:11:2] )
This generates a list of random integer numbers in the range 1,9; the list terminates when the random number is 10 (that is, each item as 1/10th probability to be the last).
random_list = List().comp( function(); n = random(1,10); return n == 10 ? oob(0): n; end )
The next, more complete example, uses a generator to fill a set of exactly 10 unique random numbers chosen in the 1..100 range. In this occasion, the role of determining the end of the comprehension is delegated to the filter.
random_set = Set().comp( [random, 1, 100], // generator, callable array function( number, myself ) // filter, using the optional "myself" param if myself.len() == 10 return oob(0) // return oob(0) as a generator to terminate end return number end )
The "comp" method returns the same object it operates on. So, it is possible to apply it on an already existing sequence to add more data to it.
Falcon allows scripts to be part of text documents, with the preprocessor <? .. ?> or <?fal .. ?> directive. Scripts saved as ".ftd" files are treated as text documents and simply echoed until one of those processor directives is encountered. Inbound scripts are executed as in the following .ftd example:
You called this script with <? print( args.len() ) ?> parameters.
FTD documents can be merged with normal Falcon scripts to form applications, where the presentation logic is in dynamic templates (the FTD files), and the application logic is stored in Falcon modules.
FTD documents can be used in driving dynamic websites. Some popular webservers (currently Apache 2), have modules which directly parse and execute ".fal" and ".ftd" scripts, providing an API which integrates in the webserver engine. It is also possible to use dynamic FTD pages along with CGI scripts.
Falcon supports error handling via the raise, try and catch statements. The raise statement can throw any Falcon item, including nil, numbers, strings, objects and so on. Library functions and external modules will usually raise instances of the Error class, or instances of a class derived from that.
The catch statement can be used to catch any type of item, a certain type (i.e. strings or integers), or instances from a certain class. Caught classes are organized on a hierarchical base, so that it is possible to provide more generic error handlers like the following example (TypeError is a library class derived from Error):
try ... code that can raise ... catch TypeError in error ... if we mixed up types ... catch Error in error ... another generic error ... catch StringType in error ... an explicit raise "something" was issued ... catch in error ... some other exception has been raised, referenced in the variable error. end
The in clause of the catch statement is optional (this means that the error itself may be discarded).
The catch statement mimics the select statement, which can be used to switch on the type or class of a given variable.
Explicit string expansion
Falcon includes an '@' unary string expansion operator that returns a string with inline '$' variable references replaced. This operation allows for formating during the substitution.
a = 123456.789 v = "formatted as" s = "a = $a, $v $(a:12rg3,.2), rounded hex as $(a:C)" printl( @ s)
a = 123456.789, formatted as 123,456.79, rounded hex as 0x1E241
- a literal string, a = , the value of the variable a, and a literal comma
- an expanded string from the variable v
- the value of a, right-aligned in a width of 12, 12r, with a grouping of 3 using comma, 3g, and then rounded to 2 decimal places, .2
- the value in upper-case hexadecimal (rounded up to closest integer) prefixed with '0x'.
Falcon is designed for embedding into and extending other systems with a linkable runtime library, libfalcon.
Falcon ships with an integrated documentation system, called faldoc, which is specifically designed to provide Falcon based libraries (be they native C++ code or module sets written in Falcon) with maintainable documentation.
All I/O operations happening at engine or at virtual machine (script execution) level are delegated to a centralized Virtual Filesystem Provider, to which external modules or embedding application facilities are allowed to register dynamically. Subscribed Virtual Filesystems abstract I/O operations as directory read, file creation and stream opening, and can be addressed from within scripts by URI. This makes it possible to load modules or open resources from any VFS (as network resources or compressed/crypted archives), which may include special virtual locations provided by third party modules and/or by applications embedding the engine.
In versions 0.8.x, the separate Threading module provides full multithreading to scripts, while starting from version 0.9.x the "Threading" module is integrated in the standard modules and threading support is provided directly inside the main engine. The multithreading model is agent oriented, and data across threads must be explicitly shared through several possible sharing mechanisms. Each thread runs a different virtual machine, which runs separately from any operation happening in the others (as i.e. garbage collection). This allows for efficient parallel processing and 0 contention outside the control of the script developer.
Falcon supports quasi-parallel coroutining. Coroutines are code executed in time slices or during idle times by the Virtual Machine. They provide a lighter parallel approach than the full threading model and allow full visibility of program global data through different coroutines. Explicit cooperation of each coroutine is required, (i.e., each coroutine must check for data availability before blocking reads).
The Falcon compiler contains a meta-compiler that supports macro expansions. A Falcon Virtual Machine in the standard compiler drives the meta-compiler. Output generated from the meta-compiler is sent to the language lexer as if part of the original source. Using \[ ...\] escape sequences, it is possible to dynamically write the contents of the program being compiled by printing it:
\[ printl( "printl( 'Hello world' )" ) \]
The keyword macro provides a simplified candy-grammar interface to compile-time meta-programming.
Strings prefixed with an 'i' are recognized as exported (international) strings. Declaring the language used in a module through the directive statement, it is possible to indicate which is the native language in which strings are written, as in the following example:
directive lang=fr_FR // uses 5 characters ISO language code > i"Bonjour à tout le monde!"
The translated string table is applied to the modules at load time.
Feathers standard library
Supporting modular programming, Falcon ships with Feathers, the standard module suite, which integrates the built-in core module, containing the basic I/O and language-integrated base functions, classes and objects.
Feather modules currently include:
- Compiler - Reflexive compiler and dynamic plugin loader module.
- Configuration Parser - Complete configuration file parser support.
- Logging - High performance parallel logging facility.
- MXML - Very fast and simple Minimal XML parser (compatible with XML 1.0).
- Process - Interface to cross platform process support (start, kill, pipes...)
- Regular Expressions - PCRE 7.x compatible regular expression library interface.
- Socket - BSD sockets cross platform networking support.
- Threading (since 0.9.0) - Multithreading structures support.
- ZLib - Interface for simple compression routines.
The core VM and official modules, (including Feather modules and other community provided support modules) are all written in C++. Some very low level module and engine elements are written in C and Assembly.
Falcon is distributed through installers on Mac OS X and Windows systems (where building and installing is a more articulated process), or through self-building source packages on various open systems as Linux or OpenSolaris.
On the latter systems, Falcon is usually supported and generally kept up to date on various distributions, among which:
- ↑ Getting Falcon
- ↑ Bleeding edge
- ↑ Falcon Programming Licence 1.1
- ↑ Falcon authors
- ↑ Falcon VM Opcode Format
- ↑ Falcon online source code
- ↑ ComputerWorld interterview with Giancarlo Niccolai, with some background on HASTE
- ↑ 8.0 8.1 Falcon International strings
- ↑ Falcon functions and procedural programming
- ↑ Functional Falcon
- ↑ 11.0 11.1 11.2 Class object-oriented Falcon
- ↑ Falcon source code, class list
- ↑ Falcon prototype-based object-orientation
- ↑ Falcon message oriented assertions explained
- ↑ Falcon Tabular Programming
- ↑ Falcon list comprehension
- ↑ Templates explained in the Falcon Showdown
- ↑ Falcon exception handling
- ↑ String expansion
- ↑ Embedding the Falcon engine in other applications
- ↑ Faldoc
- ↑ Falcon coroutines
- ↑ Falcon runtime meta compilation
- ↑ Falcon Feathers library
- ↑ http://www.falconpl.org/index.ftd?page_id=official_download
- The Falcon programming language in a nutshell at the ACM Digital Library
- Template:Cite manual
- Template:Cite manual
- Template:Cite manual
- Survival Guide on wiki
- Falcon website
- Falcon community wiki
- Falcon community forum
- Press on Linux Journal
- Press on Free Software Magazinees:Falcon (lenguaje de programación)