Overview

Expreva is a small programming language based on arithmetic and algebra expressions.

The grammar and concepts are influenced by functional, list-processing, and scripting languages.

It runs essentially as a calculator, a stack-based virtual machine that interprets a set of instructions. This is designed for safely evaluating expressions in an isolated environment, extending the language with permitted features to interact with the outside world.

The goal is a language suitable for education and end-user programming, for example: in a spreadsheet formula, as a data transport format, or dynamic content for web documents.

Table of Contents

Getting Started

Click on an expression and see its result on the left side of the page.

Example: 1 + 2 + 3

Type some numbers in the expression box, then click Evaluate to see the result change.

This process of transformation is called evaluating an expression to get its value.

In other words, you run an expression and it returns a value.


Here is a more advanced example:

((x, y, z) => x + y + z)(4, 5, 6)
  • The first part creates a kind of expression called a function.
  • The second part runs it, giving some values as input.
  • The function calculates and returns a value as output.

We'll see what that means, and what we can do with it, as we explore the language.

Language Reference

Symbol

The basic building block of an expression is a symbol.

A symbol is made of one or more of the following characters.

0123456789
abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
.=+-*/\%^!'"<>()[]{};_

You can also use characters from any language, likeあいうえお.

Symbols are separated by a white space or new line.


A symbol can be one of the following types:

Number

Example: 42 2.5

Boolean

There are two kinds of boolean symbols: true and false.

Operator

An operator works with one or more symbols to produce another symbol.

OperatorDescriptionExample
+Add1 + 2
-Subtract3 - 4
*Multiply5 * 6
/Divide7 / 8
^Exponentiation9 ^ 10
=Assignmentx = 12

Comparison

These operators are used to compare symbols on its left and right sides.

OperatorDescriptionExample
==Equal1 + 2 == 3
!=Not equal1 + 2 != 3
>Greater than3 * 3 > 3 + 3
<Less than1 + 1 < 2
>=Greater than or equal2 * 2 >= 2 + 2
<=Less than or equal3 + 3 <= 2 + 3
&&And2 == 2 && 3 == 3
||Or2 == 2 || 3 == 3

Group

The open and close parentheses() group symbols together.

This is used to control the order of operations in an expression.

See the difference between (1 + 2) * 3 and 1 + (2 * 3).

Statement

A statement is an expression that is not operating on any other expression.

In the following, there are three statements.

x = 2
y = x * 3
z = y * y * 4

The result of multiple statements is the value of the last statement.


Statements are separated by a white space or new line.

The exception is if a line starts or ends with an operator that connects to another expression.

1
+2

Such cases are rare, but if needed, use the punctuation ; to end a statement.

1;
+2

Conditional

Use the operators? and: to create a conditional expression.

It is used to control the flow of opearations based on a condition.

Such an expression has 3 parts.

  • Condition that evaluates to true or false
  • True branch to evaluate when true
  • False branch to evaluate when false
4 * 8 == 32 ? 'Yes' : 'No'

Comment

A comment is any text you want to write that is not evaluated.

It's useful for including extra information, for example, to explain how an expression works.

Use // to comment the rest of the line.

1 + 1 // Hello!

Create a comment block spanning multiple lines using/* and*/.

/*

Here is a comment.

*/

String

A string is some text created with the punctuation' called a single quote.

Example: 'hi'

When you click on the example, you see that the result does not include the punctuations.

' is an operator that returns what's between them, called the value of the string.

Escape character

To include' itself in the string, use another punctuation\ before it.

'It\'s a beautiful day in the neighborhood.'

\ is called a backslash. It is used to escape the character after it, making it a string instead of a punctuation.

Variable

A variable is a name that points to another symbol.

The name has one or more characters, alphabets and numbers only. It must start with an alphabet.

Example: distance

When you click on the above example, you see the result is empty. This is because the variable doesn't have any value yet.

To make a variable point to a symbol, use the = operator. This is called assigning a value.

distance = 50

The result of variable assignment is the value itself.

Now, when you evaluate the variable distance, it will return its value.


A variable name cannot have a space in it. Use the underscore_to separate words.

total_distance = 100

Function

A function takes an input, evaluates an expression, and returns an output.

Define

Use the operator=> to define a function.

x => x + 1

A function without a name is called an anonymous function.


Assign it to a variable to give the function a name.

Usually a function name starts with a verb, because it performs an action.

add_one = x => x + 1

This is useful if you plan to use it more than once.

add_one(3) + add_one(4)

Arguments

The left part of a function definition is a list of inputs, called arguments.

Use() to pass arguments, separated by a comma.

(x, y) => x + y

Here, x and y will be passed as inputs when the function is called.

Each argument is assigned to a variable of that name, in the order given.


The argument list can be empty if the function doesn't need input.

() => 123

If there's only one argument, the() is not necessary.

x => x * x

Argument Defaults

The assignment operator = can be used to provide initial values for missing function arguments.

f = (x = 1, y = 2) => x * y
f(3)

Call

Call a function with(), optionally with a list of arguments.

say_love = (x, y) => 'I love '+x+' and '+y+'!'

say_love('apples', 'bananas')

Use () to call an anonymous function immediately after creating.

(x => x + 1)(2)

Apply

Another way to call a function is to apply an expression to it.

Use the operator-> after an expression to call a function with it as the first argument.

square = x => x * x

(3 + 3)->square

Notice how the applied function is given as a variable, and doesn't need() after it.

This is equivalent to writing square(3 + 3).


The apply operator-> is like a pipeline, passing the result of an expression to the next function.

It can make the flow of values easier to follow when chaining together multiple functions.

square = x => x * x
double = x => x * 2
triple = x => x * 3

3->square->double->triple

You can see that the initial value is squared, doubled, then tripled.

Compare to the following way of calling functions, where you must think "backwards" to visualize the flow of operations.

triple(double(square(3)))

You can mix the two styles to organize an expression.

square(3)->double->triple

Using functions

A function can be passed as an argument to another function.

[ 1, 2, 3 ]->map(x => x + 1)

Or after an apply operator.

1 -> x => x + 1

A function can return another function.

(x => y => x + y)(5)(6)

List

To create a list of items, use the open and close square brackets[].

Use a comma , to separate each item.

[ 1, 2, 3 ]

A list can have any kind of item, including a function, the result of an expression, or another list.

[
  true,
  2 * 3 + 1,
  f = x => x * x,
  f(12),
  [ 'apples', 'oranges' ]
]

List Item

To get an item from a list, use a period. after it, and the index of the item.

An index is a number for the position of an item, counting from zero.

First, let's create a list and put it in a variable.

colors = [ 'red', 'green', 'blue' ]

Then get items by their index.

  • colors.0
  • colors.1
  • colors.(1 + 1)

The last example shows the index can be given as an expression.

You can get an item from any expression that returns a list.

get_letters = () => ['a', 'b', 'c']
get_letters().1

Item of Item

If a list item is a list (or an object), you can combine multiple . operators.

tic_tac_toe = [
  [ 'o', '.', '.' ],
  [ '.', 'x', '.' ],
  [ 'o', 'x', 'o' ]
]
tic_tac_toe.1.1

Assign list item

a = [ 0, 0 ]
a.1 = 1
a

List Functions

There are a number of built-in functions for working with a list.

Use the operator-> after a list to call these functions.

[ 1, 2, 3 ]->pop

You can also call them with() by passing a list as the first argument.

pop([ 4, 5, 6 ])

Notice that some functions, for example search, will return another function to be called with more arguments.

size

size returns the number of items in a list.

['red', 'green', 'blue']->size
search

search looks for an item in a list, and returns its position index.

  • ['red', 'green', 'blue']->search('blue')
  • ['red', 'green', 'blue']->search('purple')

If it can't find the item, it will return -1.

join

join puts two lists together and returns a new list.

['red', 'green', 'blue']->join(['white', 'black'])

If given a string, it's used as a separator to combine all items into a string.

['red', 'green', 'blue']->join(' and ')

push

push adds one or more items to the end of a list, and returns the list itself.

['white']->push('purple', 'pink')
pop

pop removes an item from the end of a list, and returns the item.

[1, 2, 3]->pop
insert

insert adds one or more items to a list at a specified index, and returns the list.

[0, 1, 2, 3]->insert(2, 'Here is index 2')
slice

slice gets a section of a list and returns a new list with those items.

It takes two arguments: start index and end index.

[1, 2, 3, 4 ,5]->slice(2, 4)

If you don't pass an end index, it will get from start index to the end of the list.

[1, 2, 3, 4 ,5]->slice(2)

If the start index is negative, it will get from the end of the list.

[1, 2, 3, 4 ,5]->slice(-2)

map

map calls a given function with each item in the list, and returns a new list with what the function returned.

['red', 'green', 'blue']->map(
  (item, index) => (index + 1)+'. '+item
)

It passes two arguments to the function, the item and its index.

filter

filter calls a given function with each item in the list: if the function returns true, it keeps the item. At the end, it returns a new list with those items.

[1, 2, 3, 4, 5]->filter(
  (item, index) => item >= 3
)

It passes two arguments to the function, the item and its index.

reduce

reduce takes a list and adds up a total of some type, such as a number, string, or list.

[1, 2, 3, 4, 5]->reduce(
  (total, item) => total = total + item,
  0
)

reduce takes two arguments:

  • A function
  • An initial value to use, called an accumulator.

In the above example, the accumulator starts with the value of zero.

For each item in the list, the given function is called with the accumulator and the item. It's expected to return a new value for the accumulator. At the end, you get the final value.


Object

An object is a kind of list where the items are in pairs, called a key and a value.

It is sometimes called a dictionary, because you "look up" a value by its key.

To create an object, use the open and close curly brackets {}.

{
  type: 'dog',
  color: 'red'
}

Key-value pair

Use a colon : between key and value.

{ key: 'value' }

Use a comma , to separate key-value pairs.

{ x: 1, y: 2, z: 3 }

Key as string

If a key has a space in it, pass it as a string.

{ 'key with space': 1 }

Dynamic key and value

The key and value can be an expression.

x = 'total'
{
  (x): 1 + 2
}

Notice that () is used to set the key to the value of the variable x.

Variable as key and value

For setting a variable's name as key and its value to an object, you can skip the :.

key = 'value'
{ key }

Value

To get a value, use the operator . and the name of key after an object.

{ x: 1, y: 2, z: 3 }.x

To use a dynamic key, wrap it in ().

key = 'z'
{ x: 1, y: 2, z: 3 }.(key)

If the value is an object (or a list), you can combine multiple . operators.

{
  parent: {
    child: 'here!'
  }
}.parent.child

Assign value to key

a = {
  b: {}
}
a.b.c = 'hi'
a

Object Functions

There are a number of built-in functions for working with an object.

Use the operator -> after an object to call these functions.

{ a: 1, b: 2 }->keys

You can also call them with () by passing an object as the first argument.

keys({ c: 3, d: 4 })
size

size returns the number of keys in an object.

{ x: 1, y: 2, z: 3 }->size
keys

keys returns the keys in an object as a list.

{ x: 1, y: 2, z: 3 }->keys

set

set assigns a key and its value to an object, and returns the object.

{ x: 1, y: 2, z: 3 }->set('a', 0)

If you pass an object instead of a key, it will set all keys and their values.

{ x: 1, y: 2, z: 3 }->set({ a: -1, b: -2 })
unset

unset removes a key and its value from an object, and returns the object.

{ x: 1, y: 2, z: 3 }->unset('x')->unset('y')

Advanced Operators

Compound Assignment

There are shortcuts for assigning a new value to a variable, based on its existing value.

Let's say we start with x = 0. Click on it for the examples below.

Compound AssignmentExampleEquivalent
++x++x = x + 1
--x--x = x - 1
+=x += 2x = x + 2
-=x -= 2x = x - 2
*=x *= 2x = x * 2
/=x /= 2x = x / 2

Spread operator

The spread operator... is used to assign a list of values from a variable or expression.

List

It can spread values into an list.

x = [ 1, 2, 3 ]
[ 0, ...x, 4 ]
Object

With objects, it spreads key-value pairs.

x = { c: 3 }
{
  a: 1,
  b: 2,
  ...x
}

If the same key exists, it will be overwritten with a new value.

x = { c: 3 }
y = { c: 4 }
{
  a: 1,
  b: 2,
  ...x,
  ...y
}
Function arguments

When used in a function argument, it gathers a list of values into a variable.

f = (x, ...y) => y
f(1, 2, 3)

Future Plan

Language

  • Type system
    • Check and explicit conversion of boolean, number, string, list, object
    • Minimal concept of type, usable as class/struct/mixin
  • Null-coalescing operator ?= ?.??

Long Term

  • Fun ways to learn and introduce the language

  • Libraries

    • Math functions
      • Currency values with fixed decimals and rounding modes
      • Floating-point arithmetic: .1 + .2 should equal .3
      • Big numbers: 9999999999999999
    • Canvas for drawing
    • Music functions and data structures
    • Database in browser local storage
  • Integrated development environment

    • Editor
    • Syntax highlighting
    • Import and export programs
  • Implementation in TypeScript

  • Implementation in WebAssembly