Next Article in Journal
On Graphical Symmetric Spaces, Fixed-Point Theorems and the Existence of Positive Solution of Fractional Periodic Boundary Value Problems
Previous Article in Journal
Quantum Tomography: From Markovianity to Non-Markovianity
 
 
Font Type:
Arial Georgia Verdana
Font Size:
Aa Aa Aa
Line Spacing:
Column Width:
Background:
Article

MxPL: A Programming Language for Matrix-Related Operations

by
Mehmet Cemil Aydoğdu
*,†,
Özge Aydoğdu
and
Hüseyin Pehlivan
Department of Computer Engineering, Karadeniz Technical University, Trabzon 61080, Turkey
*
Author to whom correspondence should be addressed.
These authors contributed equally to this work.
Symmetry 2024, 16(2), 181; https://doi.org/10.3390/sym16020181
Submission received: 19 December 2023 / Revised: 26 January 2024 / Accepted: 30 January 2024 / Published: 2 February 2024
(This article belongs to the Section Computer)

Abstract

:
It is important to establish solid mathematical knowledge throughout the education period. Matrices are important mathematical objects commonly used in many diverse disciplines, including mathematics, engineering, and science. Most problems encountered in such disciplines are represented by mathematical models with various types of matrices, and solved through some applications of matrix algebra. Although simple or advanced operations of matrices can be performed by using modern programming languages, it usually results in a large fragment of code with a low level of readability due to a complicated sequence of control statements. On the other hand, special-purpose languages handle these operations via library functions, presenting poor integration with other programming environments, and less programming flexibility and practice. This paper addresses the design and development of a programming language, called MxPL, which supports matrix-related mathematics with the provision of some basic structures and functions. Firstly, a grammar that is compatible with the usual notations of matrices is constructed and the parser is produced. Then, the code verifier and interpreter for MxPL programs are implemented. Some code examples are presented to illustrate the performance of several sophisticated matrix operations. The comparative analysis of MxPL is conducted with modern programming languages based on language features.

1. Introduction

A programming language, with its finite set of grammatical rules, acts as a bridge between programmer and machine. This bridge embodies a delicate symmetry as concise instructions translate into complex outcomes, shaping computer systems and programs that impact fields like education, medicine, and security. The widespread usage of computer-based systems in many different fields of science and engineering makes programming languages essential to have several attractive features, including simplicity, efficiency, abstraction, compactness, naturalness, and locality. Another essential feature is that their source code can easily be integrated into different system environments [1,2].
In the literature, programming languages can be classified into two main categories: special and general-purpose ones. Special-purpose languages especially serve to develop real-time applications that deliver superior operational performance during interpretation or execution. They can provide a more efficient and easier way to solve a certain class of problems [3,4,5,6,7] and can hide the runtime code to increase the system security. Some illustrative programming areas include document formatting [8,9,10], relational database query [11,12,13,14], symbolic computation [15,16,17,18], hardware description [19,20,21,22], and animation and modeling [23,24,25,26].
General-purpose languages are designed to develop software applications that can solve a more general set of problems. They often favor a particular style of programming supported by different high-level structures. From the classification based on their fundamental features, there arise several programming paradigms, including imperative programming [27,28,29], functional programming [30,31,32], logical programming [33,34,35], and object-oriented programming [36,37,38,39]. However, this classification is obviously not very restrictive. A programming language can support the symmetry of more than one programming paradigm, enabling flexibility and adaptability.
The development of science and technology fields such as engineering, finance, and informatics requires advanced mathematical knowledge and computational ability. It is important to establish solid mathematical knowledge throughout the education period. There are various software applications developed using special- or general-purpose languages, which facilitate expressing and performing mathematical operations. Typical examples are MATLAB [15], Maple [16], and Mathematica [17]. These applications are also widely used as auxiliary tools in educational and scientific studies. However, they are primarily developed for commercial purposes, and they cannot be easily integrated into general-purpose programming environments. Although function libraries are documented in detail, the syntax related to their programming structures, which may be very different from mathematical notations, is not adequately explained. Compared to general-purpose languages, source data may contain syntax components that can have different meanings.
Another family of programming languages is developed for mathematical modeling and optimization. Some particular instances are AIMMS [40], AMPL [41], LINGO [42], GAMS [43], Mosel [44], LPL [45], OMNI [46], PCOMP [46], and OPL [46]. In general, the modeling languages represent real-world problems via mathematical models that contain a proper set of relationships, such as equalities and logical expressions. They are mainly equipped with basic programming structures needed to mathematically formalize the problems. However, these structures are not purely mathematical in terms of their syntax and semantics, where some code components can contain different types of loop and selection statements together with strict evaluation of expressions. In addition, they do not offer much flexibility and support for integration into other language environments, which is still a challenge.
Matrices are mathematical objects defined as a bi-dimensional array of numbers arranged in one or more rows and columns. They are commonly used in most areas of mathematics, science, engineering, and business due to their close relation to linear systems of equations. For instance, in computer science, there is a wide application range of matrices, encompassing such topics as computer graphics, robotics, machine learning, message encryption, and game theory. In other disciplines, matrices also play a major role in the formalization of topics including electrical circuits, optics, quantum mechanics, probability, statistics, and marketing.
The field of matrix manipulation boasts a rich history of research, encompassing diverse approaches. Studies delve into matrices either directly or indirectly, manifesting in the form of general-purpose matrix function libraries, specialized matrix software, and dedicated matrix programming languages. One example is MATLANG [47], a formal language specifically designed for manipulating matrices through collinear algebra operations. Notably, MATLANG focuses on fundamental algebraic operations, excluding computationally intensive calculations like matrix inversion, which are frequently employed in scientific computing contexts. Within the domain of scientific computing for Python, NumPy [48] holds a pivotal position as a specialized library. While it does not cater exclusively to matrix manipulation, NumPy empowers multidimensional array programming, rendering it a valuable tool for a range of matrix operations, as demonstrated in previous studies. However, integrating NumPy into workflow requires a pre-existing installation of Python alongside the utilization of Python’s Package Management System (Pip) to download and install the NumPy library itself. Moreover, it is noteworthy that, due to its primarily function-based nature, NumPy may not be the most optimal choice for explicitly learning the underpinnings of matrix operations and their associated algorithms. Building upon previous research in tensor algebra compilation, the authors propose a novel compiler targeting a programming model specifically designed for handling sparse arrays, including matrices [49]. Their contribution demonstrates the construction of a general compiler for array programs operating on sparse data structures. Malik et al. [50] present Mat2Stencil, a novel domain-specific language (DSL) specifically designed for expressing and compiling partial differential equation (PDE) solvers on structured grids. This innovative framework leverages a structured sparse matrix abstraction, enabling the modular, flexible, and user-friendly construction of a wide range of solver components. While the paper builds a grammar for a matrix, the study primarily focuses on PDE solvers on structured grids. Benaddy et al. [51] propose a novel programming language specifically designed for elementary matrix operations. While they posit the language’s suitability for high school mathematicians due to its intuitive syntax and support for any-dimensional matrices, a detailed evaluation of its development process and utilized tools is absent from their paper. Furthermore, the presented example suggests an orientation towards performing pre-defined matrix operations rather than fostering a comprehensive understanding of matrix algebra concepts. Doornik et al. [52] introduce Ox, a matrix programming language specifically designed for econometrics and statistics. This versatile language features a C/C++-inspired syntax and a comprehensive library of mathematical and statistical functions, facilitating efficient manipulation of matrices and statistical data. Despite its focus on matrix operations, Ox has gained widespread adoption within the econometrics and statistics communities. While a free version for academic use is available, Ox operates under a closed-source licensing model, potentially limiting its broader utilization and community-driven development. The language has undergone continuous evolution, with the most recent release being Ox 6 [53]. MATX [54] emerges as a high-performance language designed for scientific and engineering computation. While it prioritizes both efficiency and user-friendliness, its functionality appears primarily focused on fundamental matrix-based operations. Notably, MATX does not explicitly compute the matrix operations, which might limit its accessibility for educational purposes and community-driven development efforts.
Mathematical models of scientific problems, which utilize matrices, comprise a large collection of operations, both with basic and more advanced arithmetic. Using existing programming languages, it is possible to perform such matrix operations as addition, multiplication, inverse, and determinant, as well as row and column operations. However, the task of programming these operations via general-purpose languages usually results in a large chunk of code that is not easy to read and understand. On the other hand, special-purpose languages generally support these operations via library functions, requiring very little programming and math knowledge. It is thought that utilizing a language that boasts a straightforward mathematical syntax could significantly enhance the comprehension of matrix operations during the educational journey. Such a language could serve as an effective educational tool, streamlining the learning process and promoting better understanding.
In this study, we aim to develop a programming language called MxPL to make use of both programming- and matrix-related mathematics at a moderate level. The development process involves the resolution of many language issues associated with formal grammar specification, lexical analysis and token generation, syntax analysis and parse tree construction, and semantic analysis and type checking, as shown in Figure 1. The language interpreter deals with all these issues using the JavaCC tool [55], which assists the generation of abstract syntax trees. An MxPL program is evaluated via its corresponding syntax tree constructed at the parsing phase. Some illustrative examples of what the language syntax is like are presented through the programming code of several sophisticated matrix operations. Finally, the study compares MxPL to modern programming languages like C, Java, and Python, as well as numerical computing environments like Breeze, MATLAB, NumPy, R, and ALGLIB, based on various language features and metrics. The central aim of this research endeavor is to develop a straightforward language system that bears a resemblance to mathematical syntax and can be readily acquired.

2. Materials and Methods

2.1. MxPL Snytax

The expressive structure of a programming language is obviously managed by its syntax. The MxPL language is designed for an easier representation of matrices and the mathematical operations on them than the general-purpose languages. It provides a straightforward syntax of some useful notations for matrix definitions and manipulations.
Listing 1 presents an illustrative code snippet [56] that showcases the computation of the matrix determinant in Python (pure Python). The function has been implemented using a recursive approach, albeit with the inclusion of iterative statements. This hybrid implementation may lead to a diminished level of readability and comprehensibility.
Listing 1. The determinant function in Python.
Symmetry 16 00181 i001
The motivation of the study is to create a language that has clear and similar mathematical syntax. The MxPL language developed with this motivation provides a straightforward syntax of some useful notations for matrix definitions and manipulations. The MxPL version of the determinant function is provided in Section 3.1 as Example 4.
A matrix is a bi-dimensional array of numbers with m rows and n columns, which is referred to as an m × n matrix. In the MxPL language, it is defined as follows in accordance with ordinary mathematical notations:
A = [ [ a 11 , a 12 , , a 1 n ] , [ a 21 , a 22 , , a 2 n ] , [ a m 1 , a m 2 , , a m n ] ]
A matrix can also be considered as a single-dimensional array or two-dimensional array. Two examples of such matrices of sizes 1 × 3 and 2 × 3 are provided below:
A = [ [ 1 , 2 , 3 ] ]
B = [ [ 1 , 2 , 3 ] , [ 4 , 5 , 6 ] ]
Matrix is a special data type supported by the MxPL language, which can contain elements of a numerical type such as integer or decimal. In addition, it is allowed to define matrices with a single value, which is considered to be a matrix of size 1 × 1. Similarly, an array corresponds to a matrix with one row. Some examples are as follows:
A = [ 1.2 ] [ [ 1.2 ] ]
B = [ 1 , 2 , 3 ] [ [ 1 , 2 , 3 ] ]
It is also possible to assign values of rational type to variables. A matrix element can be a rational number, represented as a ratio of two integer numbers. Rational numbers can be constructed using the division symbol “/”, as indicated below:
A = [ 1 / 2 ] [ [ 1 / 2 ] ]
B = [ 1 / 2 , 1 / 3 ] [ [ 1 / 2 , 1 / 3 ] ]
Functions are one of the fundamental structures of programming languages. The MxPL language provides a simple and articulable syntax for them. The general syntax of a function definition can be provided as follows:
f u n c n a m e ( p 1 , p 2 , , p n ) { b o d y } = e x p r e s s i o n
In this syntax, functions are defined as equations on either side of the “=” equality sign. The word f u n c n a m e corresponds to the name of a function with formal parameters p 1 , p 2 , , p n . The word "body", which is written between curly braces, represents the main body of the function, and, if not required, it can be omitted. The word "expression" evaluates the return value of the function, which can be any value of numerical or matrix types.
The evaluation of the MxPL source code is always initiated by calling a function called main, as in many other programming languages. The source code of a simple program containing the definition of the functions main and solve is shown in Listing 2.
Listing 2. The definitions of solve and main functions in MxPL.
Symmetry 16 00181 i002
This program outputs the solution of the following system of equations, where the expression 1 / A corresponds to the inverse of matrix A, which is mathematically represented by A 1 . Note that, for matrices (e.g., A and B), the operation B / A means A 1 B , which is different from the division of scalar values a and b with the meaning of b / a = b 1 / a . Similarly, as the division operator is left associative, the matrix operations A / B / C will be evaluated like C 1 B 1 A .
2 x 1 6 x 2 + 9 x 3 = 1
3 x 1 + 2 x 2 + 6 x 3 = 2
x 1 + 8 x 2 3 x 3 = 3
The syntax of the MxPL language is largely derived from those of imperative and functional programming languages. The body of functions is written in the imperative style, while the right-hand side of the function equations is conducted in the functional style.
Additionally, MxPL’s syntax incorporates support for both piecewise function and pattern-matching paradigms for function definition, thereby expanding its expressive capabilities. Listing 3 presents distinct illustrations of creating an identity matrix by utilizing piecewise function and pattern matching.
Listing 3. The examples for identity matrix construction.
Symmetry 16 00181 i003

2.2. Parsing

Parsing is the process of grammatical analysis of the source data. There are many general-purpose parser generation tools, also called compiler–compiler ones, such as YACC [57], Bison [58], SableCC [59], and JavaCC [55]. These tools automatically produce source code in some modern languages, such as C, C++, and Java, for LL(k) or LR(k) parsers, using formal language grammars. Thus, they make it easier to perform the task of constructing a parser [60].
JavaCC is one of the popular parser generators used in the literature. It transforms an EBNF grammar into an LL(k) parser, generating source code for it in the Java language. We first design a formal grammar and then translate it into the JavaCC format. This section goes into the details of implementing the lexer and the parser through the lexical and syntactic description of the MxPL language.

2.2.1. Grammar Design

The syntax analysis of a programming language starts with the design of a formal grammar. There are several mathematical notations to define formal grammar in the literature. A common one is the Backus–Naur Form (BNF), which includes a set of production rules with some terminals and non-terminals. Another one is an extended version of BNF, called the Extended Backus–Naur Form (EBNF). Unlike BNF, EBNF includes an additional set of meta-characters such as “∗”, “+”, “|” and “?”. The main components of these notations are production rules, shortly called rules, which relate non-terminals to one another. Each rule has left-side and right-side definitions separated by symbols such as “=”, “ : : = ”, or “→”. A formal grammar consists of a sequence of one or more rules.
For the MxPL language, the formal grammar is provided in Listing 4, which also specifies the operator-related semantic structure. The usual precedence and associativity of the operators are two semantic aspects that can be represented by the grammar rules. Note that a matrix can be produced by the rule “Matrix” as a one- or two-dimensional list.
Listing 4. Formal grammar for the MxPL language.
Symmetry 16 00181 i004

2.2.2. Lexical Analysis

In lexical analysis, a stream of words is produced by processing source data taken as input. This task is performed by a language component called a lexer or scanner. It converts a sequence of characters into a sequence of tokens, removing whitespace characters and comments.
The token definitions for MxPL, which are provided in the TOKEN block of the JavaCC specification file, are shown in Listing 5. Related to the definitions specified in the S K I P block (including whitespace characters, as shown in Listing 5), the lexer does not produce any corresponding token. The tokens whose names begin with the symbol #, such as N U M and S T R , are used as part of other definitions.
Listing 5. Token list of The MxPL language.
Symmetry 16 00181 i005
The I D token represents the name of a variable, an argument, a parameter, or a function, which must start with a letter, followed by letters or digits. The N U M and D N U M tokens correspond to integer and double values, respectively. There are many other tokens defined for operators, symbols, and keywords. Given the token definitions in Listing 5, the lexical analysis process produces the following sequence of tokens for the statement A = [ 1 , 2 , 3 ] .
ID   AEQ   LBRACKETS   NUM   COMMA   NUM   COMMA   NUM   RBRACKETS  
This token sequence specifies that the definition order of the tokens in Listing 5 is important. For each word, the lexer scans in the source data, all the token definitions are examined from top to bottom, and, by selecting the first one matching the word, the corresponding token is produced. Note that the token definitions listed for keywords come before that of the ID token since the latter can match all sequences of characters in input data.

2.2.3. Syntactic Analysis

This kind of analysis is performed by another language component called parser, by transforming the input data into a form of structured data that is easier to process. It analyzes a sequence of tokens depending on the syntactic structure of a programming language and, if the parsing is successful, builds a data structure (called an abstract syntax tree) representing the related input data.
There are two main classes of parsers: namely LL(k) and LR(k). A significant difference between those two parsers is the direction of their derivation regarding the input data. A LL(k) parser analyses the input from left to right using the leftmost derivation. Unlike the LL(k), an LR(k) parser performs the rightmost derivation of the input. As the JavaCC tool can generate the LL(k) parsers, it is used to construct an LL(1) parser that can parse the MxPL source data. The LL(1) parser can select a grammar rule depending on one token consumed from the source data.
Concerning each rule of the MxPL grammar, the LL(1) parser is built via some method definitions, usually one method per rule. In this way, they call each other in the same way that the grammar rules do each other. Listing 6 shows a few of the method definitions for the LL(1) parser using the JavaCC format. The corresponding token names in Listing 5 are used to define the rules.
Listing 6. The definition of parser methods in the JavaCC format.
Symmetry 16 00181 i006

2.2.4. Class Representation

In Java, the terminals and non-terminals of the language can be represented by objects. For this purpose, a syntax class is defined for each grammar rule that contains an operator or keyword. The definition of similar or alternative syntax classes is completed by inheriting from the same superclass. This approach simplifies the creation and manipulation of the parse tree. Some syntax classes of MxPL are shown in Figure 2.

2.2.5. Tree Representation

A tree representation of the source code, called abstract syntax tree (AST), is built upon the success of the syntax analysis. It is created by the parser as a result of linking syntax objects together in a hierarchical order. Each node in the AST structure corresponds to a syntax component in the source code. The internal nodes of AST contain the operation-related components, such as operators and keywords, while the leaf nodes contain the data-related ones, such as constants and variables.
The JavaCC tool plays an important role in the production of syntax trees. As in many parser generators, it allows attaching a sequence of semantic actions to the definition of each parser method. A semantic action is a fragment of Java program code that produces data required for a certain node of the syntax tree. Listing 7 shows some parser methods along with the code blocks that are added to generate the syntax tree.
Listing 7. Java code fragments creating a matrix-related node of the AST.
Symmetry 16 00181 i007

2.3. Evaluation

The evaluation process deals with two main tasks: semantic analysis and code interpretation. The tasks are performed by two separate language components, namely semantic analyzer and code interpreter, traversing through the AST nodes. The implementation of both components is based primarily upon the Visitor design pattern, which is one of the behavioral design patterns [61]. This section discloses the description of these components, defining and implementing two Java interfaces called Accept and Visitor.

2.3.1. Visitor

The Visitor design pattern provides an efficient way to evaluate data stored in a tree data structure. It separates the class representation of an object in a tree node from the operations on that. In this way, the pattern enables the definition of a new operation for an object that requires no change in its class representation.
The use of the Visitor pattern involves implementing two interfaces named Accept and Visitor. The former must be implemented by each syntax class, defining the accept method in that interface. Similarly, the latter must be completed by a separate class, containing the definition of one visit method for each syntax class. In Listing 8, the Visitor interface named I V i s i t o r is defined with the prototypes of some visit methods. The return types of the methods are specified as Object in order to allow different evaluations on the syntax tree.
Listing 8. The definition of a Visitor Interface with some (abstract) visit methods.
Symmetry 16 00181 i008

2.3.2. Semantic Analysis

The parsing process can only check the syntactic correctness of source data, but the output of this process must also be used to verify the semantic validity of the same data before the interpretation. The semantic analysis refers to the process of relating syntax components to their language-dependent meanings. Its main task is to infer type information for all the identifiers in the source code.
For type verification requirements, a symbol table is created using the definitions of the identifiers contained in the source code. An identifier can be the name of a variable, a formal parameter, or a function, which is added as a symbol to the symbol table. There are some distinctive fragments of code where a particular identifier is inserted into the symbol table. Symbols are created on the first reference, that is, when the related identifier first appears in the source code. This can either be an expression consisting of the identifier itself or a function definition of which the identifier is a formal parameter.
As in C, the MxPL language has a flat block structure for functions and a nested block structure for variables, containing inner blocks with local scope variables enclosed in a global scope. All occurrences of a variable in a local scope are required to have the same data type. The data type of a variable is inferred from the first value assigned to that variable. So, the names of the identifiers that hold values of different types must be different from each other. On the other hand, global variables are single-valued and cannot be reassigned, which is needed to support the lazy evaluation of function parameters (see Section 2.3.3).
Listing 9 shows the S y m b o l T a b l e class defined to store all identifiers together with their type information. The b e g i n S c o p e ( ) method forms a new level of scope as the e n d S c o p e ( ) method returns to the previous level of scope. The p u t ( ) method binds the name of each variable or formal parameter to its type, and the name of each function to its parameters and return type. The binding information of a particular identifier is returned by the g e t ( )  method.
Listing 9. The SymbolTable class.
Symmetry 16 00181 i009
The semantic analysis of an MxPL program takes place in two phases. The first phase is to build the symbol table and the other one is to type-check the statements and expressions. The two-phase approach makes the analysis easier since the functions can be mutually recursive. That is, in the case of type-checking a call to a function, it would be always possible to look up the related binding in the symbol table. These phases are handled by the classes S y m b o l V i s i t o r and T y p e V i s i t o r that are implemented from the I V i s i t o r interface.
The S y m b o l V i s i t o r class provides some v i s i t ( ) methods that create and maintain the symbol table to keep track of the semantics of identifiers. Visiting the abstract syntax tree, these methods ascertain the identifier definitions in a program and insert them into the symbol table. For instance, the v i s i t ( ) method in Listing 10 deals with variable definitions. It adds the name and type of a variable in a certain level of scope to the symbol table. Note that the v i s i t ( ) method checks whether a variable is defined with values of more than one type and, if so, then it reports a message related to the error.
Listing 10. A visit() method for a variable definition.
Symmetry 16 00181 i010
The T y p e V i s i t o r class provides another set of v i s i t ( ) methods that type-check statements and resolve the types of expressions. Once again, visiting the abstract syntax tree, these methods examine the identifier used in a program, consulting the symbol table to obtain its binding information. Some particular checks can be provided as follows:
  • Are values assigned to variables compatible with their type?
  • Do all variables hold a value when they are used?
  • Do all formal parameters have unique names?
  • Are all called functions defined?
For instance, the v i s i t ( ) method in Listing 11 is concerned with the type-checking of addition expressions represented with the P l u s class.
Listing 11. A visit() method for type-checking an addition expression.
Symmetry 16 00181 i011
Some other checks must be performed for the matrix data type. As stated in Section 2.2.4, matrix data are held in a two-dimensional array and there are no constraints on the number of elements in rows and columns of a matrix. So, it is necessary to check that each matrix row (i.e., each sub-array) has the same number of elements. In addition, the type checker needs to infer a type from a matrix definition. In a program, it is possible to define a matrix using a collection of elements of different data types, such as rational numbers, doubles, and integers. For the sake of precision of calculations, the type system does not allow a matrix to have both rational and double elements. However, elements of the other two different types can be used in the definition of a matrix. Since integer elements are implicitly converted into rational or double ones, the inferred type will be either rational or double.
The final check is associated with matrix operations where the operands must have a suitable size for a specified operation. For example, an expression of matrix multiplications requires that the number of columns in the first matrix ( A n x m ) be equal to the number of rows in the second matrix ( B m x p ). MxPL uses dynamic typing for matrices since they can be constructed both statically and dynamically. So, the type-checking issues associated with matrices, such as validity of index and compatibility of sizes, are resolved before accessing an element in a matrix or performing a binary matrix operation.
Listing 12 shows the P r i n t V i s i t o r class, implemented from the I V i s i t o r interface, which provides the visit methods for printing some fragments of the MxPL program code. It basically meets some debugging or error printing requirements.
Listing 12. The PrintVisitor class defined for printing some MxPL code fragments.
Symmetry 16 00181 i012
Out of syntax classes, the extended definition of the P l u s class is provided with the accept method in Listing 13.
Listing 13. The extended definition of the Plus class.
Symmetry 16 00181 i013
The I V i s i t o r interface can easily be used for very different evaluation purposes. Similar to the definition of the P r i n t V i s i t o r class, we use it to define the T y p e V i s i t o r and E v a l V i s i t o r classes that serve as a semantic analyzer and a code interpreter, respectively.

2.3.3. Evaluator

The evaluation phase operates on the abstract syntax tree decorated with type-based operations, such as identifier bindings and implicit conversions, during the semantic analysis. It is possible to translate the abstract syntax directly to the corresponding fragments of code at a lower level. This kind of translation involves many other phases that are usually target-machine-dependent, such as instruction selection, register allocation, and code generation. Without committing to such machine-specific issues, MxPL programs are interpreted by an evaluator that is dynamically loaded on the Java Virtual Machine. It does not apply any optimizations over the programs being executed because they are not translated to intermediate representation.
The MxPL evaluator is represented by a visitor class named E v a l V i s i t o r , which has one v i s i t ( ) method for each syntax class. These methods cooperate with each other by recursively traversing the abstract syntax tree and interpreting the nodes that contain objects belonging to syntax classes. Listing 14 shows the implementation of the v i s i t ( ) method that evaluates the objects of type P l u s .
Listing 14. The visit() method for evaluating Plus objects.
Symmetry 16 00181 i014
The instantaneous values of all variables with local and global scope in an executed program are stored as the pair (variable and value) in an object of the S y m T a b l e class provided in Section 2.3.2, just like the pair (symbol and type). The state of the object is continuously updated throughout the lifetime of variables (i.e., local, global, and formal ones), which is determined by their scope.
The evaluation of matrix multiplication is handled within the visit() method with the formal parameter of an object of type Times. Initially, if two operands of the operation are matrices, it is verified whether the number of columns in the first matrix A n x m is equal to the number of rows in the second matrix B m x p , in accordance with the well-known mathematical rule of matrix multiplication. This verification step guarantees the size consistency of two matrices just before multiplying them. The relevant fragment of code is provided in Listing 15.
Listing 15. The visit() method for evaluating Times objects.
Symmetry 16 00181 i015
For the index of matrices, there are two possible classes of syntax, which are represented by objects of types Index and Range. The former object is evaluated regarding an integer, while the latter object is associated with a range of integers, possibly beginning and ending with the attributes “start” and “end”. The definitions of both classes (Range and Index) can be found in Listing 16.
Listing 16. The definitions of the syntax classes Index and Range.
Symmetry 16 00181 i016
During the evaluation process, it is necessary to verify the validity of the matrix indices. This involves ensuring that the index value is both a positive integer and smaller than the corresponding matrix dimension. The visit() method provided in Listing 17 is used to verify the index validity, with the help of the chkIndex() method.
Additionally, the dimension of a matrix can be dynamically modified through some special functions, such as rotate() and merge(). During the static analysis, only the element type is verified, if possible. Therefore, after the first assignment of a variable with a matrix, all later assignments of that variable in the same local scope are only restricted to matrices that may be of different size.
An important part of evaluation is to keep track of variables that are created in a certain scope. The actual parameters of a function are accessed in a lazy fashion. More specifically, an actual parameter that is an expression is evaluated at the time of the first access to its corresponding formal parameter in the body of the called function. So, the scope of local variables usually extends outside the function bodies in which they are defined. The L a z y E v a l class presented in Listing 18 is used to hold the scope number via which a specific actual parameter must be evaluated.
The method of lazy evaluation (also called call-by-need) is not applied when functions are defined using patterns with a constant value. In general, a formal parameter is either a pattern or a simple variable, while a pattern is either a constant or an expression of the form n + k (a variable name n and a positive integer k). A function can have a separate body for each different pattern, resulting in more than one equation. During the invocation of such a function, first, the actual parameter is evaluated and then the patterns are checked from top to bottom. The first matching of a pattern leads to the evaluation of the corresponding function body (or equation). Listing 19 shows the match() function used to select an equation of the function with formal parameters matching the actual ones of the callee function.
Listing 17. The definitions of the methods visit() and chkIndex().
Symmetry 16 00181 i017
Listing 18. The LazyEval class that holds an actual parameter expression and its scope.
Symmetry 16 00181 i018
Listing 19. The determination of the function equation conforming to actual parameters.
Symmetry 16 00181 i019

2.4. Interpreter Construction

This section addresses the integration of the interpreter components described in the previous ones. The interpreter is constructed by the integration of three main components, that is, the syntax controller, the semantic controller, and the code evaluator. These components are driven by the invocation of three distinct methods: the p a r s e ( ) method, the t y p e C h e c k ( ) method, and the e v a l u a t e ( ) method.
The p a r s e ( ) method carries out the lexical and syntactical analysis of the code, generating its corresponding tree structure of the abstract syntax. The t y p e C h e c k ( ) method then verifies the validity of the syntax tree. Lastly, the evaluate() method deals with the execution of the related program. All possible parsing, validation, and evaluation errors are reported simultaneously. Listing 20 shows the implementation of these methods.
Listing 20. The integration of the interpreter components.
Symmetry 16 00181 i020
The interpreter can be produced by placing all the source files in the same directory and running the following commands:
$>  javacc Parser.jj
$>  javac *.java
The JavaCC parser generator creates parser classes according to the definitions in the file P a r s e r . j j . The compilation process of the interpreter produces the executable I n t e r p r e t e r . c l a s s file. This executable can be run by specifying the path of the file containing the program code together with the desired option of output at the command line. The possible compilation options are listed in Table 1.
The following is an example of how the interpreter program would be run for a sample program file:
$>  java Interpreter -r sample_program.mx

3. Results and Discussion

3.1. Program Examples

In this section, some examples are provided to demonstrate the syntax of the language. In addition, it is compared with the C programming language in terms of a matrix operation of a determinant.
Example 1.
Table 2 shows how to initialize a variable of type ‘Matrix’ in the MxPL language.
Example 2.
Table 3 demonstrates samples of accessing elements of a matrix in MxPL. The matrix provided in Example 1 is used as the input matrix in the examples below:
The colon operator (:), also known as the range operator, is used to access the entire row or column of a matrix. When the colon operator is placed on the right-hand side of the comma, it specifies that the entire row of the matrix should be accessed. This can be seen in sample 2, where the statement A [ 1 , : ] returns the entire second row of matrix A. Conversely, when the colon operator is placed on the left-hand side of the comma, it specifies that the entire column of the matrix should be accessed. This can be seen in sample 3, where the statement A [ : , 1 ] returns the entire second column of matrix A. Moreover, when the colon operator is placed between two integers, it specifies that the specific rows or columns between the integers should be accessed. In sample 4, A [ 1 : 2 , : ] returns the second and third rows of matrix A.
Example 3.
The transpose operation of a matrix is the process of exchanging its rows and columns. The transpose of the matrix written in MxPL is provided below in Listing 21.
Listing 21. Imperative and functional transpose function examples in MxPL.
Symmetry 16 00181 i022
The t r a n s p o s e ( x ) function in MxPL takes a matrix, say x, as its input and returns the transpose of x. The transpose of a matrix is a new matrix that has the rows and columns of the original matrix exchanged. To compute the transpose of x, the t r a n s p o s e ( x ) function uses two helper functions written in MxPL, namely size(x) and m a t r i x ( n , m ) . The s i z e ( x ) function returns the size of matrix x as a matrix. The m a t r i x ( n , m ) function creates a new zero matrix with the size n by m.
Example 4.
The determinant of a square matrix is a number that is calculated using the elements of the matrix. It can be used to find the inverse of a matrix and to solve systems of linear equations. Listing 22 provides an example of a function that calculates the determinant of a matrix.
Listing 22. An imperative and functional examples of the determinant in MxPL.
Symmetry 16 00181 i023
Symmetry 16 00181 i024
Example 5.
Echelon form is a specific type of matrix transformation that is used to solve linear equations. A matrix can be converted into echelon form using a set of basic row operations, such as row swapping (Type I), row scaling (Type II), and row addition (Type III). In the C programming language, the execution of each of these operations necessitates the use of iterative constructs, such as loops. A reduced row echelon function written in the MxPL language is presented in Listing 23.
Listing 23. ReducedEchelon() function in MxPL.
Symmetry 16 00181 i025
In C, the execution of each of the row operations (Types I, II, and III) requires the use of iterative constructs, such as loops. This results in the code containing nested loops, which makes it longer and more difficult to read and understand.
An example of the main() function calling the echelon function is presented in Listing 24.
Listing 24. Calculating Matrix inverse using ReducedEchelon function.
Symmetry 16 00181 i026

3.2. Comparative Analysis

The comparative analysis is performed using some important aspects of modern programming languages, including their fundamental principles and features. There are various metrics (also called design principles) that can lead to the evaluation of programming languages [2]. In this way, metrics such as readability, portability, and efficiency are used to compare the languages C, C++, Java, Python, and Haskell. Programming paradigms with significant distinctive effects on the language metrics are also included in the comparison. The results are provided in Table 4.
Below is a brief overview of the evaluation metrics in Table 4.
Maintainability: This refers to the ability of a software program to be easily maintained and updated over time. It includes the ability to add new features, as well as to identify and correct errors that may arise during the software development process.
Writability: This metric measures how easily a programming language can be used to write code. It is closely related to the language syntax and how quickly developers can grasp it to produce efficient code.
Readability: This refers to how easily a program’s code can be understood by other developers.
Orthogonality: This refers to the consistency and predictability of how different language features interact with each other.
Uniformity: This evaluates how consistent the language is in its use of structures that have similar meanings.
Extensibility: Ability to expand the language’s capabilities beyond its core set of features, allowing programmers to introduce new functionalities and adapt it to specific needs.
Efficiency: This metric measures how quickly a program can be executed and how much memory it requires.
Reliability: This measures how accurately a program performs its specified calculations based on the input data.
Portability: This refers to the ease with which code written for one platform or environment can be executed on another without significant modifications.
Other comparative analyses can be conducted based on certain language features [62]. The MxPL language provides some distinguished structures and features that are distinctive and intrinsic ones of imperative and functional programming paradigms. The features such as type inference, pattern matching, and lazy evaluation are purely functional, while the ones such as explicit type annotations loops and assignments are imperative. Table 5 shows the comparison results.
The third comparative analysis presented in Table 6 is related to the basic features of MxPL and some sophisticated numerical environments. Such prominent settings have various levels of abilities and skills. As shown in Table 6, MATLAB stands out for its extensive toolbox and thriving community. However, some users are likely to find it less accessible due to its high cost. NumPy is an open-source and free library that is a strong substitute for MATLAB, with significant computational capabilities. Its portability is limited by its reliance on the Python environment, and its user-friendliness is often debated, with some considering it less intuitive than MATLAB. Breeze and R are other open-source alternatives that are both dependent on the environment. They have some superior aspects regarding performance enhancements, such as R’s statistical prowess or Breeze’s speed and memory efficiency.
They normally have a relatively long learning curve for many developers, especially because of either complex or poorly documented syntax as well as syntactic components that can carry different meanings. MxPL differentiates itself by prioritizing ease of learning and programming and platform independence through its minimal external dependencies. With just the widely available Java Runtime Environment (JRE) needed, the MxPL interpreter can run smoothly on a variety of devices, making it a good choice for people looking for something portable and easy to use.
A final comparison is conducted based on language syntax constructs. Table 7 shows basic syntax supported by the related programming environments for some common arithmetic and matrix operations. Note that ALGLIB is not included in Table 7 since its syntax might vary slightly depending on the programming language binding. When compared to other numerical computing environments, it has been observed that MxPL employs row-major ordering for matrices, in contrast to column-major ordering used by MATLAB, Breeze, and R. Moreover, MxPL uses 0-based indexing, a feature shared with Numpy and Breeze, whereas MATLAB and R have 1-based indexing.

4. Conclusions

This paper presents the development of a programming language, called MxPL, which provides high-level structures for mathematical calculations related to matrices. A matrix can be defined as a two-dimensional array of elements of integer, double, or rational type, and manipulated through a small set of basic operations based on rows and columns. With a syntax similar to mathematical notations, the MxPL language supports some functional features, including type inference, pattern matching, and lazy evaluation. The study consists of several stages, such as formal grammar design, lexer and parser production, syntax tree construction, type verification, and code evaluation. An LL(k) grammar is designed in accordance with the requirements of the JavaCC tool that is used to generate the language parser. The abstract syntax tree built by the parser serves to verify and evaluate MxPL programs. Some specific matrix operations are programmed to illustrate the syntax and semantics of the language. Moreover, using certain language features and metrics, a comparative analysis is performed with modern programming languages such as Java and Phyton.
In programming languages and tools, matrix operations are usually performed through high-level library routines. For instance, Phyton and MATLAB provide various linear algebra routines for more complicated operations such as inverse and decomposition. However, they have relatively less programming support for elementary algebraic operations on rows or columns of matrices. This kind of low-level operation can be programmed via a large fragment of code that is not easy to read and maintain. The MxPL language supports the manipulation of the relevant mathematical operations through the provision of special functions for elementary matrix operations. Thus, it is possible that a certain matrix operation can be formed by composing a collection of elementary ones in a similar style to functional programming.
The primary objective of this study is to develop a simple language that is similar to mathematical syntax and easily learned. Performance optimizations were excluded from the scope of the study. Therefore, the performance analysis and improvements of the language could be the subject of another study. Additionally, given that the language could be a useful tool for mathematics education, this topic could be investigated in the field of educational sciences.
The language can be extended to support various elementary functions that perform basic operations for linear algebra and other topics of mathematics. Such functions would especially serve to meet the operational requirements of mathematical models based on scientific problems. It is also important to establish a common set of I/O operations such as reading from or writing to text files. There is another need for language structures that can handle the arrangement of mathematical functions in different ways, as in the calculation of the roots of a particular function via fixed point iterations. These requirements can be fulfilled by adding new data types and keywords to the language syntax or by developing a language library.
The current work of MxPL focuses on foundational aspects of its semantic analysis, including type checking and scope resolution. More advanced techniques of semantic analysis, such as liveness or available expression analysis [63], would play a critical role in enhancing and bolstering the language’s security, dependability, and accuracy. These techniques probe farther into the understanding of the program, revealing richer meaning and fostering robust growth. Therefore, an important direction for future MxPL research is the incorporation of advanced semantic analysis features. On the other hand, we also recognize the necessity of a well-rounded strategy that takes the associated trade-offs into account. Combining advanced semantic analysis techniques with static analysis tools, such as WALA [64], LiSA [65], and Julia [66], may be helpful in providing insights into possibly troublesome software behaviors. In the MxPL ecosystem, this combination strategy may be especially useful for large-scale codebases.

Author Contributions

Conceptualization, M.C.A., Ö.A. and H.P.; methodology, M.C.A.; software, M.C.A.; formal analysis, M.C.A.; investigation, M.C.A.; resources, M.C.A.; data curation, M.C.A. and Ö.A.; writing—original draft preparation, Ö.A., M.C.A. and H.P.; writing—review and editing, Ö.A. and M.C.A.; visualization, Ö.A. and M.C.A.; supervision, H.P. All authors have read and agreed to the published version of the manuscript.

Funding

This research received no external funding.

Data Availability Statement

Data are contained within the article.

Conflicts of Interest

The authors declare no conflicts of interest.

Abbreviations

The following abbreviations are used in this manuscript:
MxPLA Programming Language for Matrix-Related Operations
JavaCCJava Compiler Compiler
ASTAbstract Syntax Tree
BNFBackus–Naur Form
EBNFExtended Backus–Naur Form
LL(k)Leftmost Derivation
LR(k)Rightmost Derivation

References

  1. Louden, L.K.C.; Lambert, K.A. Programming Languages: Principles and Practices, 3rd ed.; Cengage Learning: Boston, MA, USA, 2011. [Google Scholar]
  2. Harper, R. Practical Principles for Programming Languages, 2nd ed.; Cambridge University Press: New York, NY, USA, 2016. [Google Scholar]
  3. Giner-Miguelez, J.; Gómez, A.; Cabot, J. A domain-specific language for describing machine learning datasets. J. Comput. Lang. 2023, 76, 101209. [Google Scholar] [CrossRef]
  4. Borsotti, A.; Breveglieri, L.; Reghizzi, S.C.; Morzenti, A. General parsing with regular expression matching. J. Comput. Lang. 2023, 74, 101176. [Google Scholar] [CrossRef]
  5. Kokash, N.; Moodie, S.L.; Smith, M.K.; Holford, N. Implementing a domain-specific language for model-based drug development. Procedia Comput. Sci. 2015, 63, 308–316. [Google Scholar] [CrossRef]
  6. Lopes, L.; Martins, L.F. A safe-by-design programming language for wireless sensor networks. J. Syst. Archit. 2016, 63, 16–32. [Google Scholar] [CrossRef]
  7. Vasić, M.; Soloveichik, D.; Khurshid, S. CRN++: Molecular programming language. Nat. Comput. 2020, 19, 391–407. [Google Scholar] [CrossRef]
  8. Richter, W.T. TEX and Scripting Languages. In TUGboat, Proceedings of the Practical TEX 2004 Conference, San Francisco, CA, USA, 19–22 July 2014; TEX Users Group: Providence, RI, USA, 2014; Volume 25, pp. 71–88. [Google Scholar]
  9. Lamport, L. LateX: A Document Preparation System, 2nd ed.; Addison-Wesley: Boston, MA, USA, 1994. [Google Scholar]
  10. Berners-Lee, T.; Cailliau, R.; Pellow, N.; Secret, A. The World Wide Web Initiative, CERN. 1993. Available online: http://info.cern.ch/hypertext/WWW/TheProject.html (accessed on 19 December 2023).
  11. Oppel, A. SQL: A Beginner’s Guide, 4th ed.; McGraw-Hill Education: New York, NY, USA, 2015. [Google Scholar]
  12. IBM Security QRadar. Ariel Query Language (AQL) Guide v7.3.1; IBM Corp: New York, NY, USA, 2017. [Google Scholar]
  13. Johnson, S. Query-by-example (QBE). In Database Management Systems; McGraw-Hill Publisher: New York, NY, USA, 1999. [Google Scholar]
  14. Feuerstein, S.; Pribyl, B. Oracle PL/SQL Programming; O’Reilly Media, Inc.: Newton, MA, USA, 2005. [Google Scholar]
  15. Higham, D.J.; Higham, N.J. The Matlab Guide, 3rd ed.; SIAM: Philadelphia, PA, USA, 2017. [Google Scholar]
  16. Maplesoft - Software for Mathematics, Online Learning, Engineering (n.d.-b). Maple. Available online: https://www.maplesoft.com/ (accessed on 25 August 2021).
  17. Trott, M. The Mathematica Guidebook for Programming; Springer: New York, NY, USA, 2014. [Google Scholar]
  18. Bosma, W.; Cannon, J.J. Handbook of Magma Functions; The University of Sydney: Sydney, Australia, 1996. [Google Scholar]
  19. Perry, D.L. VHDL: Programming by Example, 4th ed.; McGraw-Hill Education: New York, NY, USA, 2002. [Google Scholar]
  20. Thomas, D.E.; Moorby, P.R. The Verilog Hardware Description Language, 5th ed.; Springer: New York, NY, USA, 2002. [Google Scholar]
  21. Augustsson, L.; Schwarz, J.; Nikhil, R.S. Bluespec Language Definition; Sandburst Corp.: Andover, MA, USA, 2001. [Google Scholar]
  22. Müller, W.; Rosenstiel, W.; Ruf, J. (Eds.) SystemC: Methodologies and Applications; Springer Science & Business: Berlin/Heidelberg, Germany, 2007. [Google Scholar]
  23. McKinley, M. The Game Animator’s Guide to Maya; Sybex: Alameda, CA, USA, 2006. [Google Scholar]
  24. Blain, J.M. The Complete Guide to Blender Graphics: Computer Modeling & Animation, 6th ed.; CRC Press: Boca Raton, FL, USA, 2020. [Google Scholar]
  25. Reinhart, C.; Breton, P.F. Experimental validation of Autodesk 3ds Max® Design 2009 and DAYSIM 3.0. Leukos 2009, 6, 7–35. [Google Scholar] [CrossRef]
  26. Tavakkoli, A. Game Development and Simulation with Unreal Technology, 2nd ed.; Routledge: London, UK, 2018. [Google Scholar]
  27. Balman, T. Computer assisted teaching of FORTRAN. Comput. Educ. 1981, 5, 111–123. [Google Scholar] [CrossRef]
  28. Kernighan, B.W.; Ritchie, D.M. The C Programming Language; Prentice Hall Professional Technical Reference: Haboken, NJ, USA, 1988. [Google Scholar]
  29. Wakerly, J. The programming language Pascal. Microprocess. Microsyst. 1979, 3, 321–326. [Google Scholar] [CrossRef]
  30. Sussman, G.; Steele, G.L., Jr. Scheme: A interpreter for extended lambda calculus. High. Order Symb. Comput. 1998, 11, 405–439. [Google Scholar] [CrossRef]
  31. Turner, D. An overview of Miranda. ACM Sigplan Not. 1986, 21, 158–166. [Google Scholar] [CrossRef]
  32. Jones, S.P. Haskell 98 Language and Libraries: The Revised Report; Cambridge University Press: New York, NY, USA, 2003. [Google Scholar]
  33. Sterling, L.; Shapiro, E.Y. The Art of Prolog: Advanced Programming Techniques, 2nd ed.; The MIT Press: Cambridge, MA, USA, 1994. [Google Scholar]
  34. Somogyi, Z.; Henderson, F.; Conway, T. The execution algorithm of Mercury, an efficient purely declarative logic programming language. J. Log. Program. 1996, 29, 17–64. [Google Scholar] [CrossRef]
  35. Hermenegildo, M.V.; Bueno, F.; Carro, M.; López-García, P.; Mera, E.; Morales, J.F.; Puebla, G. An overview of Ciao and its design philosophy. Theory Pract. Log. Program. Prolog. Syst. 2012, 12, 219–252. [Google Scholar] [CrossRef]
  36. Stroustrup, B. An overview of C++. In Proceedings of the 1986 SIGPLAN Workshop on Object-oriented Programming, New York, NY, USA, 9–13 June 1986; pp. 7–18. [Google Scholar]
  37. Arnold, K.; Gosling, J.; Holmes, D. The Java Programming Language; Addison Wesley Professional: Glenview, IL, USA, 2005. [Google Scholar]
  38. Hejlsberg, A.; Torgersen, M.; Wiltamuth, S.; Golde, P. C# Programming Language; Addison-Wesley Professional: Boston, MA, USA, 2010. [Google Scholar]
  39. Van Rossum, G.; Drake, F.L., Jr. Python Tutoria; Centrum voor Wiskunde en Informatica: Amsterdam, The Netherlands, 1995; p. 620. [Google Scholar]
  40. Bisschop, J.; Roelofs, M. AIMMS: The Language Reference; Paragon Decision Technology B.V.: Haarlem, The Netherlands, 1999. [Google Scholar]
  41. Fourer, R.; Gay, D.M. Extending an algebraic modeling language to support constraint programming. INFORMS J. Comput. 2002, 14, 322–344. [Google Scholar] [CrossRef]
  42. Schrage, L. Optimization Modeling with LINGO; LINDO Systems, Inc.: Chicago, IL, USA, 1999. [Google Scholar]
  43. Bisschop, J.; Meeraus, A. On the development of a general algebraic modeling system in a strategic planning environment. In Mathematical Programming Study; Springer: Berlin/Heidelberg, Germany, 1982; pp. 1–29. [Google Scholar]
  44. Heipcke, S. Applications of Optimization with Xpress-MP; Dash Optimization: Blisworth, UK, 2002. [Google Scholar]
  45. Hürlimann, T. Index Notation in mathematics and Modelling Language LPL: Theory and Exercices; Department of Informatics University of Fribourg: Fribourg, Switzerland, 2007. [Google Scholar]
  46. Kallrath, J. Modeling Languages in Mathematical Optimization; Springer: Boston, MA, USA, 2004. [Google Scholar]
  47. Brijder, R.; Geerts, F.; Van den Bussche, J.; Weerwag, T. MATLANG: Matrix operations and their expressive power. ACM Sigmod Rec. 2019, 48, 60–67. [Google Scholar] [CrossRef]
  48. Harris, C.R.; Millman, K.J.; Van Der Walt, S.J.; Gommers, R.; Virtanen, P.; Cournapeau, D.; Wieser, E.; Taylor, J.; Berg, S.; Smith, N.J.; et al. Array programming with NumPy. Nature 2020, 585, 357–3627. [Google Scholar] [CrossRef] [PubMed]
  49. Henry, R.; Hsu, O.; Yadav, R.; Chou, S.; Olukotun, K.; Amarasinghe, S.; Kjolstad, F. Compilation of sparse array programming models. Proc. Acm Program. Lang. 2021, 5, 1–29. [Google Scholar] [CrossRef]
  50. Cao, H.; Tang, S.; Zhu, Q.; Yu, B.; Chen, W. Mat2Stencil: A Modular Matrix-Based DSL for Explicit and Implicit Matrix-Free PDE Solvers on Structured Grid. Proc. Acm Program. Lang. 2023, 7, 686–715. [Google Scholar] [CrossRef]
  51. Benaddy, M.; El Habil, B. A programming language for matrices operations and LATEX code generation. In Proceedings of the 2016 International Conference on Engineering & MIS (ICEMIS), Agadir, Morocco, 22–24 September 2016; pp. 1–4. [Google Scholar]
  52. Doornik, J.A. Object-Oriented Matrix Programming Using Ox, 4th ed.; Timberlake Consultants Press: London, UK, 2001. [Google Scholar]
  53. Doornik, J. An Object-Oriented Matrix Programming Language Ox 6; Timberlake Consultants Ltd.: London, UK, 2009. [Google Scholar]
  54. Koga, M.; Furuta, K. MaTX: A high-performance programming language (interpreter and compiler) for scientific and engineering computation. In Proceedings of the IEEE Symposium on Computer-Aided Control System Design, Napa, CA, USA, 17–19 March 1992; pp. 15–22. [Google Scholar]
  55. Kodaganallur, V. Incorporating language processing into Java applications: A JavaCC tutorial. IEEE Softw. 2004, 21, 70–77. [Google Scholar] [CrossRef]
  56. ThomIves. Available online: https://github.com/ThomIves/BasicLinearAlgebraToolsPurePy (accessed on 19 December 2023).
  57. Levine, J.R.; Mason, T.; Brown, D. Lex & Yacc; O’Reilly Media, Inc.: Sebastopol, CA, USA, 1992. [Google Scholar]
  58. Levine, J. Flex & Bison: Text Processing Tools; O’Reilly Media, Inc.: Sebastopol, CA, USA, 2009. [Google Scholar]
  59. Gagnon, E.M.; Hendren, L.J. SableCC, an object-oriented compiler framework. In Proceedings of the TOOLS USA 98 (Technology of Object- Oriented Languages and Systems), Santa Barbara, CA, USA, 7 August 1998; IEEE: Piscataway, NJ, USA, 1998. [Google Scholar]
  60. Dos Reis, A.J. Compiler Construction Using Java, JavaCC, and Yacc; IEEE Computer Society, Inc.: Piscataway, NJ, USA, 2012. [Google Scholar]
  61. Hussein, B.; Mehanna, A.; Rabih, Y. Visitor Design Pattern Using Reflection Mechanism. Int. J. Softw. Innov. 2020, 8, 92–107. [Google Scholar] [CrossRef]
  62. Biswa, K.; Jamatia, B.; Choudhury, D.; Borah, P. Comparative analysis of C, Fortran, C# and Java Programming Languages. Int. J. Comput. Sci. Inf. Technol. 2016, 7, 1004–1007. [Google Scholar]
  63. Nielson, F.; Nielson, H.R.; Hankin, C. Principles of Program Analysis, 1st ed.; Springer: Berline/Heidelberg, Germany, 1999. [Google Scholar]
  64. WALA. Available online: https://github.com/wala/WALA (accessed on 19 December 2023).
  65. Negrini, L.; Ferrara, P.; Arceri, V.; Cortesi, A. LiSA: A generic framework for multilanguage static analysis. In Challenges of Software Verification; Springer Nature: Singapore, 2023; pp. 19–42. [Google Scholar]
  66. Spoto, F. The Julia static analyzer for Java. In Static Analysis, Proceedings of the 23rd International Symposium, SAS 2016, Edinburgh, UK, 8–10 September 2016; Proceedings 23; Springer: Berlin/Heidelberg, Germany, 2016; pp. 39–57. [Google Scholar]
Figure 1. Overview of the MxPL interpreter.
Figure 1. Overview of the MxPL interpreter.
Symmetry 16 00181 g001
Figure 2. Syntax classes diagram.
Figure 2. Syntax classes diagram.
Symmetry 16 00181 g002
Table 1. The compilation options.
Table 1. The compilation options.
OptionsMeaning
-pParse the program code and print the abstract syntax tree (AST)
-cCompile the program code and generate Java bytecode
-rRun the program code (used as default)
Table 2. Matrix initialization in MxPL.
Table 2. Matrix initialization in MxPL.
A = [ [ 1 ,   2 ,   3 ,   4 ] , [ 5 ,   6 ,   7 ,   8 ] , [ 9 ,   10 ,   11 ,   12 ] , [ 13 ,   14 ,   15 ,   16 ] ] ; Symmetry 16 00181 i021
Table 3. Accessing elements of matrix.
Table 3. Accessing elements of matrix.
ExplanationInputOutput
1. To access a single element of AA[1, 1]6
2. To access the entire first row of AA[1, :]5, 6, 7, 8
3. To access the entire first column of AA[:, 1]2, 6, 10, 14
4. To access a certain part of AA[1:2, :]6, 10
Table 4. Comparison of some programming languages via evaluation metrics and programming paradigms.
Table 4. Comparison of some programming languages via evaluation metrics and programming paradigms.
MetricsMxPLCC++JavaPythonHaskell
ImperativeXXXXX
Object-oriented XXX
FunctionalX XX
EfficiencyXXXXXX
Extensibility XXXXX
MaintainabilityXXXXXX
OrthogonalityX XX
PortabilityX XX
ReadabilityXXXXXX
ReliabilityXXXXXX
UniformityX X X
WritabilityXXXXXX
Table 5. Comparison of some programming languages via certain language features.
Table 5. Comparison of some programming languages via certain language features.
AspectMxPLCC++JavaPythonHaskell
assignmentXXXXXX
loop statementXXXXX
lazy evaluationX X
pattern-matchingX X
recursionXXXXXX
type inferenceX XX
segmented functionsX X
conditionalsXXXXXX
local side-effectsXXXXXX
explicit type annotation XXXX
rational typeX X
identifier scopenestedflatnestednestednestednested
function scopeflatflatflatflatflatnested
Table 6. Comparison of Breeze, NumPy, MATLAB, ALGLIB, R, and MxPL via basic features.
Table 6. Comparison of Breeze, NumPy, MATLAB, ALGLIB, R, and MxPL via basic features.
FeatureBreezeNumPyMATLABALGLIBRMxPL
LanguageScalaPythonMATLABC/C++/FortranRMxPL
PriceFreeFreePaidPaid/FreeFreeFree
StrengthsSpeed, memory efficiencyVersatility, ease of usePowerful environment, large toolboxCross-language compatibilityStatistical focus, graphicsEase of learning and portability
WeaknessesLimited functionalityLess user-friendly than MATLABHigh costNot as beginner-friendly as PythonSteeper learning curve than PythonLimited functionality
RequirementsScala EnvironmentPython EnvironmentMATLAB EnvironmentC/C++/Fortran EnvironmentsR EnvironmentJava Run Environment
Table 7. Some operators and operations in popular numerical environments and MxPL.
Table 7. Some operators and operations in popular numerical environments and MxPL.
OperationBreezeMATLABNumpyRMxPL
Basic Indexinga(0,1)a(1,2)a[0,1]a[1L,2L]A[0,1]
Extract column of matrixa(::, 2)a(:,3)a[:,2]a[,2]A[:,2]
Elementwise additiona + ba + ba + ba + bA+B
Shaped/Matrix multiplicationa * ba * bdot(a, b)a % * % bA * B
Extract column of matrixa(::, 2)a(:,3)a[:,2]a[,2]A[:,2]
Matrix sizea.rows, a.colssize(a)a.shapedim(x)size(a)
Matrix vertical concatenateDenseMatrix.vertcat(a,b)[a ; b]vstack((a,b))rbind(a, b)append(a,b)
Matrix horizontal concatenateDenseMatrix.horzcat(d,e)[d , e]hstack((d,e))cbind(d, e)merge(a,b)
Disclaimer/Publisher’s Note: The statements, opinions and data contained in all publications are solely those of the individual author(s) and contributor(s) and not of MDPI and/or the editor(s). MDPI and/or the editor(s) disclaim responsibility for any injury to people or property resulting from any ideas, methods, instructions or products referred to in the content.

Share and Cite

MDPI and ACS Style

Aydoğdu, M.C.; Aydoğdu, Ö.; Pehlivan, H. MxPL: A Programming Language for Matrix-Related Operations. Symmetry 2024, 16, 181. https://doi.org/10.3390/sym16020181

AMA Style

Aydoğdu MC, Aydoğdu Ö, Pehlivan H. MxPL: A Programming Language for Matrix-Related Operations. Symmetry. 2024; 16(2):181. https://doi.org/10.3390/sym16020181

Chicago/Turabian Style

Aydoğdu, Mehmet Cemil, Özge Aydoğdu, and Hüseyin Pehlivan. 2024. "MxPL: A Programming Language for Matrix-Related Operations" Symmetry 16, no. 2: 181. https://doi.org/10.3390/sym16020181

Note that from the first issue of 2016, this journal uses article numbers instead of page numbers. See further details here.

Article Metrics

Back to TopTop