Introduction
Mozilla’s Rust and Microsoft’s VPL are two very different languages that have come into use in recent history. Rust is a language in development for the future of internet browsing whereas VPL is used in Microsoft’s Robotics Studio to create embedded software systems or simulations thereof. Both languages are easy to read and program in, with VPL having the slight advantage in readability. Security in both languages are high, and both have minor issues in regularity, with VPL’s issue causing a break in functionality. Rust’s security enhancement of the C based language’s unsafe memory allocation in addition to the focus on parallel programming make this language one to keep an eye on. VPL is a quick easy to use visual way to program that almost anyone can use, but its limitations keep it from being able to be used in algorithms requiring significant data manipulation.
Background and Historical Context
Rust is a programming language that was developed by a Mozilla language engineer named Graydon Hoare in 2006. Hoare began this project as an intellectual hobby to prototype an idea he theorized from working with other programming languages. Hoare’s goal was to create a language that focuses on security.[1] After showing Mozilla the results from his prototype, they decided to adopt the project in 2009 and officially released it to the public in 2010. [2] Rust compiled itself in 2011; the first alpha version of the Rust compiler was released in 2012.
Rust is similar to C, but does not have all the same controls. Some keywords such as if, else, do, while and for are present, but new keywords are included such as match.[2] The match keyword is used for multi-directional branching. The type system of Rust supports a system inspired by Haskell called traits, which can be described as ad-hoc polymorphism, or operator overload. This is when an operating, such as ‘+’ appears perform a similar function on two different types.[5] Another feature of Rust is type inference, which lets the compiler accept a variable declaration with its type assigned later through inference.
The auto keyword will allow this to occur, and declare a variable with no type. However, if a section of code comes to completion with a branch not assigning a value to the variable, the code will not compile.[4] Concurrency is supported through having tasks communicate through message passing, as opposed to direct data sharing. [2]
The goal of Rust is to challenge the unsafe C based memory systems which hold the majority of the market.[1] Having a language focused around memory security and safety will lead to a safe browsing experience. This is Mozilla’s goal with their research project Servo: to create a parallelized, safe, modular browser.[5] Microsoft VPL is a language by which programming occurs through a dataflow diagram, rather than sequential commands. The language is targeted at beginners, but can also be used for rapid prototyping. [6] The language is wrapped up in Microsoft’s Robotics Development Studio, designed for robot control, and simulation.[7]
The dataflow of VPL is sequence of connected blocks. These blocks have input and outputs, and connections to other blocks. These connections are messages sent between the blocks. Each block performs an activity such as test a variable, perform an operand, or something as complex as text to speech. This is made possible by the fact that a block may be consisting of multiple blocks itself.[6]
In June 2006, Microsoft announced Robotics Studio at the RoboBusiness Conference and Exposition[8]. An official release came later in december of the same year[7]. Visual programming languages existed long before Robotics Studio.
In 1963 Ivan Sutherland developed the first computer graphics application, Sketchpad. A very basic program that allowed basic images such as squares and circles to be created and copied [16]. Many more visual programming languages were created, and improvements repeatedly theorized including LOGO in 1967, ‘Mindstorms - Children Computers and Powerful Ideas’ in 1980[10], LEGO Mindstorms in 1998[11]. It is worth noting that support for LEGO Mindstorms is included in Microsoft Robotics Studio’s VPL. Microsoft’s Kodu Game Lab, released in 2009 is designed to be an educational tool using reactive programming in a game environment[12]. Project Spark, currently in development, is the successor to Kodu, and incorporates elements of artificial intelligence into the programming interface.[13]
Programming Constructs
There exist countless programming languages, some superior to other, and some even abandoned. To define the quality of Rust and Microsoft’s VPL, Programming Languages by Louden and Lambert uses four measurements; Efficiency, Regularity, Security, and Extensibility.[14] Efficiency, while a debatable definition, will be judged in this comparison as “How quickly and easily can a person read and write a program” as known as programmer efficiency. Regularity is sub-defined by generality, orthogonality, and uniformity. The idea of security is to “maximize the number of errors that could not be made.” Finally Extensibility allows users to add additional features into the language.[14]
Programmer efficiency further breaks down into “how quickly and easily can a person read and write in a particular language” and “How easy is it to express complex processes and structures”[14]. Rust, based on the C languages, and can be read at a glance. Methods such as println to print a line or or C type encapsulation using ‘{ }’ makes analysing scope easy as well. Familiar control structures such as if and while are also part of Rust. Type inference also increases the speed and readability of code. Complex processes and structures are more efficient in rust than its C predecessor. One reason for this, is that everything thats not a declaration, is an expression. This allows a substantial reduction in code. Figure B1. Structures such as C based structs and enums are included in Rust, as well as the Tuple structure, which is the same as a struct, except the fields do not have names.[15]
Microsoft VPL, as with most VPLs, is designed with efficiency as a top priority. The linked block methods of programming makes executions paths, and the blocks obvious in purpose. The blocks, linked and named to other blocks, contain data, methods, or other blocks, and events to direct the execution flow. All this can very easily be done with a drag and drop approach to programming associated with the included libraries and objects. As example, the Lego Mindstorms can be programmed with drag and drop objects in minutes. This method also easily ports to complex structures. Since a block can contain multiple blocks, complex structures can be very easily built, maintained, and reused, all with the simple drag and drop. However, this system also means that to some some simple work, numerous blocks may be required, where a line or two in a typed language would suffice.
Regularity, broken down into three categories; generality, orthogonality, and uniformity. Rust is still in development, and as such, its structure and capabilities are evolving, while issues are constantly being addressed. An orthogonal issue in Rust shows in the compiler’s assignment of type traits. A type trait is a built in trait assigned to types such as Send, Freeze, Share and Pod that applies properties to a type. Program execution is reliable with built in types, however, since there is no method to set these traits for user made types, execution can be unpredictable. There are already self defining traits in Rust, such as Eq and Clone, but for some reason, those four are restricted to being assigned by the compiler.[17]
Microsoft’s VPL is highly regular. Having predefined types, inputs and outputs, and a limit to functional mechanisms allows for extremely concise and predictable code. However, this extreme lack of flexibility makes certain processes difficult. This can be seen with the quick sort mentioned later. However, in the experimentation conducted later in this paper, one issue with regularity was discovered. The Text Functions block can only be used once per activity page. Other blocks can be used multiple times, in contrast to this discovered anomaly.
During the initial creation of Rust, it was decided that the language would be made with the idea of security being the focus. Data races, buffer overflow, stack overflow or access to uninitialized or deallocated memory are all impossible in Rust making rust an extremely secure language.[16]
The drag and drop nature of Microsoft VPL has the benefit of limiting the system interaction of the developer. Code that is run is usually provided making security taken care of by nature. The developer has limited access to unsecured or unsafe methods and objects.
Extensible languages are languages that are more readily adopted. Programmers like to be creative, and solve problems in unique ways, as such, extensibility is important to them. Rust is a highly extensible language. You can declare your own objects and types, and import external APIs.
Microsoft VPL is extensible, but not all inclusive. You can build your own blocks with various computations, inputs and outputs, however, there are limits. The limited number of included components in VPL makes some projects impossible. As example, there is no way to write something to socket. To do this, you would need to write the code as a service in C#, and port it into VPL. With the combination of the very secure included methods in VPL and the service imports of C#, most projects become reasonable. However, since this paper analyses the paradigms of VPL and Rust, and not C#, this extensibility introduced by C# is outside the scope of recognition, however it is noteworthy.
Experimentation
Rust, as stated previously, is similar to C based languages. As such, the Hello World program consists of opening a main function, and printing Hello World to console. The method println takes in the tokens “hello, world” with a type assumption of string and with the line terminated with a semi colon. This is very similar to cout in c. Figure A1
The Hello World program, as written in Microsoft’s VPL is a simple two blocks. One block to define a String type variable, the second block, to display a pop-up message with the contents of the variable. The lines between the two blocks show the flow of data, as such, the allocation and type of the variable is sent as a message to the next block of type dialog. Both the variable type and dialog type are pre-defined, and accessed through drag and drop. Figure A2
Each Language has very different methods of accomplishing a simple Hello World. Where Rust reads in a line by line procedural context, VPL focus’ on data flow, with one object pointing data to the next node. Both approaches very visibly understandable, quick to program, and quick to run. It is worth noting however, that the development environment of VPL, is much easier to work in then Rust. As Rust is still in its development state, there is no official development environment to use, only prefered methods of compilation.
Quick Sort as implemented by the Rust developers is where examples of this language’s benefits and traits begin to show. The algorithm is broken into three functions. The entry point, takes in a mut vector, and then passes it off to be sorted. Local variables in Rust are immutable, meaning they can’t be changed after assignment, mut allows for them to be changed. The array is verified to be above length zero, then sent to be sorted. The use of the auto type, which figures out types dynamically, new pivot points are formed on the array, then they are sent to the part function. Here, the values of the array are compared to the pivot point and sorted. Any mutable type can be used in the sort without any special comparators, constraints, or overloading. Figure A3
Microsoft’s VPL, was developed with robotics in mind, inputs, and outputs, with a few calculations performed in the middle. A quick sort was not something that is easy to implement. Figure X shows this quick sort, however, it is extremely hard to follow. The sort itself is made entirely with the methods given in the language. The difficulties of this data flow mechanism show itself most specifically in the recombination of data. To bring two separate flows into one transforms the data input into a new struct. Input1 + Input2 combined in element Combine makes data accessible through the allocation Combine.Input1. After a few combinations, this struct allocation scheme can get very complex. Figure A4
A Non-Trivial implementation of Rust, while still scarce in number, can be represented by Mozilla’s research project Servo.[16] Servo is a browser engine written and compiled in Rust. Both Rust and Servo are still under developement, and far from finished products. However, Rust, being Turing complete and being capable of compiling itself means its capabilities are great enough to perform large scale projects. Servo is designed to be highly secure, and highly parallel. While the entire project is massive in scope and unreasonable to analyse in parts or as a whole, individual modules can be pulled and analysed for comparison.
Microsoft VPL is wrapped up in Microsoft’s Robotics Studio, and as such, is mostly used in robotics, or hardware interfaces. most projects in large scale are where sensory inputs are read, analysed, and sent to a processing unit programmed in another language such as C or C#. As such, a Non-Trivial example of Microsoft’s VPL has been hard to find. So the data loader module from Mozilla’s Servo engine Figure A5 written in Rust is to be analysed.
This first line of code in the function factory() immediately brings us to a divergence in Rust and VPL. A new process is being spawned through the use of the proc command. VPL does not support parallel programming in the way rust does, but instead focuses on concurrent or distributed processing.[6] However, Rust performs inter-process communication with a queue mechanism similar to VPL’s message passing dataflow.[18] Both languages send message to different processes to perform actions.
Moving into the load function, the input argument `url` is cloned into a local variable and assigned as mutatable so that actions can be performed. The http headers are then split into a string array, and an error sent back to the task handler if the header is malformed. These operations in VPL are comprised of six activity blocks. The first takes in the url string and the second forms a string variable for the comma delimiter. These two variables are combined into one input via a join and passed into a text function block to be split. From there, a string array is made on success and an alert is thrown on failure. Both of these implementations are quick and easy to perform in both languages. The benefit of Rust is that the compiler can assign the split to multiple processors, though for the average operation in this instance, the gain would be minimal. The flow of the data and the operations performed are very clear in VPL. Programmer efficiency are high in both cases, with security and regularity on par as well. Figure A6
The next block of code checks for base64 at the end of a string, sets a local variable if it exists, then removes it from the string. Data is then sent over the the progress_chan process queue to be handled. That module is outside our current scope, but it is to be noted again however, that this message passing is similar to a data flow message pass. Most of this can be translated into VPl easily. A string can be checked for at the end of the first array index, and if it exists, is_base_64 is set. However, the second operation of parsing the end of ct_str can’t be performed. Microsoft’s VPL IDE seems to only support one text function block per activity page. When a second activity block is placed, all connections to the first are voided, and if reconnected, the second block is unable to receive the data passed through. This is a negative for VPL as it greatly affects regularity. For no apparent reason, Text Function blocks can only be used once, where other blocks can be used multiple times.Figure A7
The final function of this module is assert_parse. Here the meta data is reported back to to other processes in Servo. These processes are outside our current scope, and are merely represented by a data connection in VPL. The overall use of Rust in this example was very efficient. The code used was concise, readable, and stable. Microsoft’s VPL was quick to mimic the operations performed and remained greatly readable in great contrast to the aforementioned quicksort. However the Text Functions block’s unpredictable behavior when used multiple times made a complete recreation impossible.
The next module in Servo to be covered is is file_loader. Figure A8. This module was chosen to sample both looks and switch cases. In Rust, the flow is simple and short. The function read_all loops through a send buffer until end of file is reached sending the buffered data to another message queue. No data type for the buffer is specified to allow for all varieties of data transfers to occur. This same concept in VPL looks very different as VPL has no implicit loop, and is instead handled by recursion. For this reason, this example shows VPL’s concurrent programming setup. The action performed in the loop are a ‘dead end’ for the data flow, and occur outside the scope of the loop itself. The use of recursion to mimic this buffering structure adds a few blocks to pop an item off the list where Rust handles that functionality natively making this diagram somewhat tricky to follow. In addition, the example given in Figure ? has an error on the recursive data link because the data type of the Stream is lost. A work around for this most likely exists, however the appropriate changes to fix this error are not apparent. Figure A9
Conclusion
Rust and VPL, both very different languages are used for very different purposes. Rust, a language still in development is being used to develop browser engines of the future, and Microsoft’s VPL, whose development has been halted and replaced with Kodu and Spark, reaction based gaming creation languages. Rust’s secure memory system and message based parallel processing makes it a very safe method of parallel computing. Already adopted by both Mozilla and Samsung, the languages future will be eventful. Microsoft’s VPL is a little outdated in comparison, but still a useful prototyping language, very useful in modeling robotics. Wiring sensors to processes, and performing basic data operations. While It’s direct extensibility pales in comparison to Rust, it is unmatched in security and the visual method of programming can make for a quick turnaround in program creation.
References
1 A. Avram.“Interview on Rust, a Systems Programming Language Developed by Mozilla” G. Hoare, Internet: http://www.infoq.com/news/2012/08/Interview-Rust Aug 03 2012 [April 30 2014]
2 “Rust (programming language).” Internet: http://en.wikipedia.org/wiki/Rust_programming_language, April 15 2014 [April 30 2014].
3 L. Cardelli and P Wegner. (Dec, 1985). “On Understanding Types, Data Abstraction, and Polymorphism.” Computing Surveys. [On-line]. 17(4), pp. 471-522. Available: http://lucacardelli.name/Papers/OnUnderstanding.A4.pdf [April 30 2014]
4 P. Walton, “Rust Features I: Type Inference,” http://pcwalton.blogspot.com/2010/10/rust-features-i-type-inference.html, Oct 1 2010 [April 30 2014]
5 P. Rouget, “Servo, A Browser Engine Research Project,” http://paulrouget.com/e/servo/, June 27 2012 [April 30 2014]
6 “VPL Introduction.” Internet: http://msdn.microsoft.com/en-us/library/bb483088.aspx 2012 [April 30 2014]
7 “Microsoft Robotics Developer Studio.” Internet: http://en.wikipedia.org/wiki/Microsoft_Visual_Programming_Language, Mar 3 2014 [April 30 2014]
8 J. Fernando. “Microsoft Announces Robotics Studio” Internet:http://blogs.msdn.com/b/msroboticsstudio/archive/2006/06/20/639762.aspx Jun 20 2006 [April 30 2014]
9 M. Boshernitsan and M. Downes. (2004, Dec) Internet:http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.73.2491&rep=rep1&type=pdf. Dec 2004 [April 30 2014]
10 “Constructing Kids.” Internet:http://constructingkids.com/2013/05/15/vpl/. May 15, 2013 [April 30 2014]
11 “History of Lego Robotics.” Internet: http://www.lego.com/en-us/mindstorms/gettingstarted/historypage/. [April 30 2014]
12 E. Lerner. (2009, June), “Kodu Doesn’t Have Realistic Graphics, Huge Explosions, or Even A Way To Win. But It Just Might Change The Way We Think About The World.” Seed Magazine. [On-line] Available:http://seedmagazine.com/content/article/serious_fun/. [April 30 2014]
13 X. Matos. “Project Spark is an Evolution of Kodu's Programming Language.” Internet:http://www.joystiq.com/2013/06/13/project-spark-is-an-evolution-of-kodus-programming-language/. June 13 2013 [April 30 2014]
14 K. Louden and K. Lambert. “Language Design Criteria” in Programming Languages: Principles and Practices, 3rd Ed., Marie Lee, Massachusetts:Course Technology, 2012, pp. 27-35
15 “The Rust Language Tutorial.” Internet:http://web.mit.edu/rust-lang_v0.9/doc/tutorial.html .[April 30 2014]
16 “Mozilla Research Projects.” Internet:http://www.mozilla.org/en-US/research/projects/ .[April 30, 2014]
17 N. Matsakis. “Opt-In Builtin Traits.” Internet:http://comments.gmane.org/gmane.comp.lang.rust.devel/8735. Feb 28 2014 [April 30 2014]
18 “The Rust Reference Manual.” Internet:http://static.rust-lang.org/doc/master/rust.html [April 30 2014]
Appendix A
Rust Hello World
Figure A1
fn main() {
println("hello, world");
}
Rust Hello World pulled from http://en.wikipedia.org/wiki/Rust_(programming_language)
Microsoft VPL Hello World
Figure A2
Microsoft VPL Hello World pulled from http://msdn.microsoft.com/en-us/library/bb483092.aspx
Rust Quicksort
Figure A3
fn part<copy T>(compare_func: lteq<T>, arr: [mutable T], left: uint,
right: uint, pivot: uint) -> uint {
let pivot_value = arr[pivot];
arr[pivot] <-> arr[right];
let storage_index: uint = left;
let i : uint = left;
while i < right {
if compare_func(copy arr[i], pivot_value) {
arr[i] <-> arr[storage_index];
storage_index += 1u;
}
i += 1u;
}
arr[storage_index] <-> arr[right];
ret storage_index;
}
fn qsort[T](lteq[mutable T] compare_func, vec[mutable T] arr, uint left,
uint right) {
if (right > left) {
auto pivot = (left+right)/2u;
auto new_pivot = part[T](compare_func, arr, left, right, pivot);
if (new_pivot == 0u) {
ret;
}
qsort[T](compare_func, arr, left, new_pivot - 1u);
qsort[T](compare_func, arr, new_pivot + 1u, right);
}
}
fn quick_sort[T](lteq[mutable T] compare_func, vec[mutable T] arr) {
if (len[mutable T](arr) == 0u) {
ret;
}
qsort[T](compare_func, arr, 0u, (len[mutable T](arr)) - 1u);
}
Quicksort pulled from Rust’s std lib: https://github.com/mozilla/rust/pull/351/files
VPL QuickSort
Figure A4
Rust Non-Trivial Data_Loader
Figure A5
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use resource_task::{Done, Payload, Metadata, LoadResponse, LoaderTask, start_sending};
use serialize::base64::FromBase64;
use url::Url;
use http::headers::test_utils::from_stream_with_str;
use http::headers::content_type::MediaType;
pub fn factory() -> LoaderTask {
proc(url, start_chan) {
// NB: we don't spawn a new task.
// Hypothesis: data URLs are too small for parallel base64 etc. to be worth it.
// Should be tested at some point.
load(url, start_chan)
}
}
fn load(url: Url, start_chan: Sender<LoadResponse>) {
assert!("data" == url.scheme);
let mut metadata = Metadata::default(url.clone());
// Split out content type and data.
let parts: ~[&str] = url.path.splitn(',', 1).collect();
if parts.len() != 2 {
start_sending(start_chan, metadata).send(Done(Err(())));
return;
}
// ";base64" must come at the end of the content type, per RFC 2397.
// rust-http will fail to parse it because there's no =value part.
let mut is_base64 = false;
let mut ct_str = parts[0];
if ct_str.ends_with(";base64") {
is_base64 = true;
ct_str = ct_str.slice_to(ct_str.as_bytes().len() - 7);
}
// Parse the content type using rust-http.
// FIXME: this can go into an infinite loop! (rust-http #25)
let content_type: Option<MediaType> = from_stream_with_str(ct_str);
metadata.set_content_type(&content_type);
let progress_chan = start_sending(start_chan, metadata);
if is_base64 {
match parts[1].from_base64() {
Err(..) => {
progress_chan.send(Done(Err(())));
}
Ok(data) => {
progress_chan.send(Payload(data));
progress_chan.send(Done(Ok(())));
}
}
} else {
// FIXME: Since the %-decoded URL is already a str, we can't
// handle UTF8-incompatible encodings.
progress_chan.send(Payload(parts[1].as_bytes().into_owned()));
progress_chan.send(Done(Ok(())));
}
}
#[cfg(test)]
fn assert_parse(url: &'static str,
content_type: Option<(~str, ~str)>,
charset: Option<~str>,
data: Option<~[u8]>) {
use std::from_str::FromStr;
use std::comm;
let (start_chan, start_port) = comm::channel();
load(FromStr::from_str(url).unwrap(), start_chan);
let response = start_port.recv();
assert_eq!(&response.metadata.content_type, &content_type);
assert_eq!(&response.metadata.charset, &charset);
let progress = response.progress_port.recv();
match data {
None => {
assert_eq!(progress, Done(Err(())));
}
Some(dat) => {
assert_eq!(progress, Payload(dat));
assert_eq!(response.progress_port.recv(), Done(Ok(())));
}
}
}
VPL Non-Trivial Data_Loader
Figure A6
Figure A7
Rust Non-Trivial 2 - File_Loader
Figure A8
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use resource_task::{ProgressMsg, Metadata, Payload, Done, LoaderTask, start_sending};
use std::io;
use std::io::File;
use servo_util::task::spawn_named;
//FIXME: https://github.com/mozilla/rust/issues/12892
static READ_SIZE: uint = 1;
fn read_all(reader: &mut io::Stream, progress_chan: &Sender<ProgressMsg>)
-> Result<(), ()> {
loop {
let mut buf = Vec::new();
match reader.push_exact(&mut buf, READ_SIZE) {
Ok(_) => progress_chan.send(Payload(buf)),
Err(e) => match e.kind {
io::EndOfFile => return Ok(()),
_ => return Err(()),
}
}
}
}
pub fn factory() -> LoaderTask {
let f: LoaderTask = proc(url, start_chan) {
assert!("file" == url.scheme);
let progress_chan = start_sending(start_chan, Metadata::default(url.clone()));
spawn_named("file_loader", proc() {
match File::open_mode(&Path::new(url.path), io::Open, io::Read) {
Ok(ref mut reader) => {
let res = read_all(reader as &mut io::Stream, &progress_chan);
progress_chan.send(Done(res));
}
Err(_) => {
progress_chan.send(Done(Err(())));
}
};
});
};
f
}
VPL Non-Trivial Data_Loader
Figure A9
Appendix B
Figure B1
C Code
let price;
if item == "salad" {
price = 3.50;
} else if item == "muffin" {
price = 2.25;
} else {
price = 2.00;
}
if item == "salad" {
price = 3.50;
} else if item == "muffin" {
price = 2.25;
} else {
price = 2.00;
}
Rust Code
let price =
if item == "salad" {
3.50
} else if item == "muffin" {
2.25
} else {
2.00
};
if item == "salad" {
3.50
} else if item == "muffin" {
2.25
} else {
2.00
};
Code sample from [16].
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.