what is morfa

Morfa is a general purpose programming language with focus on performance critical tasks. It enables custom Domain Specific Language (DSL) creation and comes with a suite of packages for scientific computing.

  • statically typed with type inference for variables

  • JIT compiled and fast

  • user-defined operators

  • object-oriented, functional and generic programming

  • computational toolboxes using mathematical syntax

Morfa is currently under development, its first release is scheduled for mid-2015. Sign up for the newsletter to get updates on Morfa.

Prerelease version 0.2.0 of Morfa compiler is available for download: Win 64-bit / Linux (Ubuntu) 64-bit.

Morfa language is licensed under GPL version 3. For detailed information on licensing of Morfa components visit the licensing page.

operator ⊗
{
    kind = infix,   precedence = mul
}
alias ⊗ = kron;     // bind operator to function performing Kronecker product
operator ᵀ
{
    kind = postfix, precedence = not
}
alias $ᵀ = trans;   // $ indicates postfix operator here
var A = randn(3,4);
disp(speye(5,5) ⊗ (A * A ᵀ) );


                            
var n = 1000;
var diag = randn(n, 1);
var diag1 = randn(n-1, 1);
var T = bdiag(diag);        // create diagonal matrix
T{1} = diag1;               // substitute elements on sub- and superdiagonal
T{-1} = diag1;
T[1,1] = T[n,n];            // some additional substitution

// concatenate matrices to define the LHS of a linear system
var A = ᴹ[  T,          eye(n,n)    |
            eye(n,n),   2 * T       ];

var B = randn(2*n, 1);      // define the RHS
var x = linsolve(A, B);     // solve a block diagonal system of equations
                            
public interface OnClickListener
{
    public func onClick(view : View) : void;
}
public class View
{
    public func setOnClickListener(listener : OnClickListener) : void;
}
var view = new View;
view.setOnClickListener(new class OnClickListener
{
    public override func onClick(view : View) : void
    {}  // some implementation of event handling goes here...
});
                            
var problem = new class SymbolicOptimizationDefinition { func new()
{
    // use optimization DSL to define variables...
    variable 2 <= 'x <= 3;
    variable 'y;
    variable 'z <= 5;
    
    // ... constraints and the objective function
         'z * 'y >= 7;
    0 <= 'x * 'y <= 5;
    minimize 'x^3 * 'y - 'z + 'x * 'y * 'z;
}};
var solver = new CoinWrapper(problem, false);
solver.solve(zeros(3,1));
                            
// use parser combinators to parse signed ternary integer numbers
func digitArrayToNumber(digits : text[]) : int // ...
property ternaryInt() : Parser < int >
{
    // parse sequence of '0', '1', '2''s
    return (anyOf('0', '1', '2'))+ >> digitArrayToNumber;
}
property signedTernaryInt() : Parser < int >
{
    // parse ternary integer or negative ternary integer
    return ternaryInt | 
           char('-') -> ternaryInt >> func (n : int) { return -n; };
}        
var answer : int = parse(signedTernaryInt, "-1120");
                            
var problem = new class CallbackOdeDefinition { func new()
{
    var t = time;
    var x : Matrix = 1;
    // use DSL to define an ordinary differential equation x' = 2x
    ∂x / ∂t == func()
               {
                   return 2*x;
               };
}};
var solver = new OdepackWrapper(OdepackAlgorithm.lsode);
solver.calculate(problem, linspace(0.0, 10.0, 20));


                            
// defining maximum likelihood estimation problem for the Michaelis-Menten enzyme kinetic experiment
var likelihood = new class Likelihood { func new()
{
 
    variable 'α >= 0;                    // maximum reaction velocity,
    variable 'β >= 0;                    // Michaelis constant
    variable 'σ >= 0;
    
    // reaction velocity 'v and substrate concentration 's provided in data
    
    // the model
    model independent 'v ~~ N('α * 's / ('β + 's), ('σ * 's / ('β + 's)) ^ 2 );
}};

                            

news about morfa

releases / events
videos

v0.2.0 released


Prerelease version 0.2.0 of Morfa compiler is available for download.

Morfa at CeBIT


Imapp and Morfa will be present at CeBIT 2015, Hannover. There will be an opportunity to test drive Morfa and some of the toolboxes and Domain Specific Languages designed in Morfa.
Make sure you pay a visit to stand A51, Scale 11.

Artur Zawłocki & Paweł Kowal will be giving a short talk on Morfa during Developer World, Thu 19. March 11.20am.

Source code of two demonstration toolboxes concurrent and parsing are availble to download (MIT License).

Talk on Morfa given on CeBIT 2015 Developer World

Videos on using DSL's designed in Morfa

for whom

Morfa is a language for everyone who needs to develop fast and robust code and, at the same time, have access to high-level programming features to keep that code concise and expressive.

It is also designed for those who don't want to resort to using several programming languages to solve one problem.

The story


Coming from an econometrics/data analysis background, we have desired a language, which would allow us to define complex macroeconomic models and, at the same time, be a versatile and reliable general purpose language. We would like to have a single tool which would bridge the gap between interpreted languages like MATLAB® and R and languages like C++ and Java aimed at performance and stable software development.

Morfa is at its core a general purpose programming language: it can be used as a C++, Java or C# substitute. On the other hand it is designed so that all the math can be done as easily as possible. All mathematical and modelling features stem from natural and elegant programming constructs like classes and polymorphism, operator overloading, templates etc. No workarounds or hacks allowed, the design of the mathematical support machinery is completely transparent.

Morfa is accompanied by various libraries which handle numerical and symbolic computations - most importantly matrix operations, linear algebra, optimization and symbolic differentiation. Moreover writing own low-level algorithms results in fast code optimized using LLVM.

main features

Exceptional support for user-defined operators


  • define any identifier to be parsed as an operator - infix, postifix, prefix...

operator ∑
{
    kind = prefix,
    precedence = add
}
func ∑(summand : SomeSummableType) : SomeSummedType;
// ...
var mySum = ∑ x_i * y_j + ∑ c_k;
                        
  • ... or define custom indexing and surrounding operators

operator 〔〕
{
    kind = surrounding,
    precedence = max
}
template < TList... >
func 〔〕(sequence : TList) : void
{
    // operate on a sequence of arguments of different type
}
// ...
〔5, 5.6, "Hello World"〕;
                        

Performance and portability thanks to the LLVM


func fib(n : int) : int
{
    return if(n < 2) n else fib(n-1) + fib(n-2);
}
assert(fib(20) == 6765); // ca. 200 times faster than MATLAB® R2012a
                        

Multi-paradigm general purpose programming language


Morfa provides the typical constructs that allow stable developement of large software systems. Taking the numerical and syntactical features away, you get a language Java and C# developers will immediatly feel at home with.

  • garbage collector, debugger, C interface-friendly

  • classes and interfaces for object-oriented programming

public interface AnInterface
{
    public func doSomething() : void;
}
public class AClass : AnInterface
{
    public func doSomething() : void
    {}   // implement doing something
}
                        

  • closures and higher-order types for functional programming

public func getChecker() : (func() : bool)
{
    var condition = true;
    return func() { return condition; };
}
                        

  • templates and mixins for generic programming

template < AType >
public struct AStructure
{
    const isStruct = type.traits.IsStructType < AType >;
    public static func get() : AType
    {
        static if (isStruct)
        {
            return AType();
        }
        else if (traits(compiles, new AType))
        {
            return new AType;
        }
        else assert (false);
    }
}
                        

Interactive development in REPL console using JIT compilation


> import mcl.io.print;
> print("Hello World!");
Hello World!
> import matrix.Matrix;
> var multiplier = 2;
> var mySVD = func(m : Matrix) { return svd(multiplier * m); };
> disp(mySVD(ᴹ[1, 0 |
               0, 0 ]  ));
               
 dense real matrix, size: 2x1, type: general

   |    1
 --------
 1 | 2.00
 2 |    0
                    

Extensive standard library


Toolboxes for scientific computing


All of the features of these toolboxes are implemented in Morfa using overloading, templates and inheritance mechanisms.

  • matrix operations and linear algebra

var A = randn(n,n);             // random matrix creation
var B = T{1};                   // access the superdiagonal
A{-1} = B;                      // substitute the subdiagonal
var C = A[1..n, 1];             // access single column
var D = ᴹ[A, A |                // concatenate
          A, A ];
var E = A * A;                  // linear algebra
var F = linsolve(A, eye(n,n));
var S = svd(A);
// NOTE: none of the {}, ᴹ, | is built-in!
                    
  • linear and non-linear, constained and unconstrained optimization

// define and overload operators: variable, minimize, <=, >=, ==, etc.
// for example, within some limited scope overload:
func <=(lhs : float, rhs : Expression) : SomeAdditionalType
{
    // handle addition of a non-linear constraint lhs <= rhs
}
// ...
variable 0  <= x <= 1;
variable -∞ <= y <= 1;
-0.5 <= x*y <= 0.5;
minimize x^3 + y^2;
                    
  • ordinary differential equation solution

// define and overload operators like ∂, /, ==, e.g.:
operator ∂
{
    kind = prefix,
    precedence = not
}
// ...
∂x / ∂t == func() : Matrix
           {
               return 2*x + t;
           };
                    
  • numerical integration

// define a set of operators to naturally handle numerical integration:
operator ∫
{
    kind = prefix,  precedence = add
}
operator on
{
    kind = infix,   precedence = assign    associativity = left
}
operator ⋴
{
    kind = infix,   precedence = compare
}
// ...
∫ x * exp(-x^2 * y^3 + log(y)) on [x ⋴ [-∞, ∞], y ⋴ [-1, 1] ]
                    

authors


Michał Bernardelli


Paweł Bylica


Radosław Cybulski


Piotr Dobaczewski


Piotr Janiuk


Daniel Kłobuszewski


Paweł Kowal


Mariusz Kozakiewicz


Anna Sawicka


Juliusz Stasiewicz


Krzysztof Surdacki


Radosław Zagórowicz


Artur Zawłocki

contact morfa

Sign up for morfa newsletter

To contact the morfa team post on the mailing list morfalang-users.

Morfa is developed by imapp. To get in touch send an email to [email protected]


Projekt współfinansowany przez Unię Europejską z Europejskiego Funduszu Rozwoju Regionalnego

© Copyright imapp

Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.