Skip to content

A programming language that compiles to x86-64 assembly for math using postfix notation

License

Notifications You must be signed in to change notification settings

JakeRoggenbuck/component

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Component Logo Component Logo
A programming language that compiles to x86-64 assembly for math using postfix notation

Rust GitHub code size in bytes

About

Create a program in the interpreter or run a code file.

image

Component converts your code to RISC-V or x86-64 assembly to be run.

image

See convert-to-assembly for more info.

Component is the follow-up language to Basis which is also a math language. Component was built with insights learned from writing Basis. The main difference between the two is that Basis has a more complicated syntax which included types and data structures whereas Component uses postfix notation with the addition of functions as operations.

The code for Component and Basis use the same lexer. Component is mainly different because it has a different syntax. The lexer for basis was written generally enough that this code can be shared. It also helps that Basis is a math language inspired by postfix notation but not exclusively postfix notation.

Interactive interpreter

image

Note that the symbol > is used in code example to show that these expressions are being put into a REPL and evaluated. These symbols at the start of the expression are not apart of the syntax.

Component 0.1.0
A programming language for math using postfix notation

USAGE:
    component [FLAGS] [OPTIONS]

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information
    -v, --verbose    Print the stack and lexer information on each command

OPTIONS:
    -a, --asm <asm>              Use `x86` or `x86-64` to get x86-64 assembly and use `RISCV` or `RISC-V` for RISC-V
                                 assembly
    -f, --filename <filename>    Specify an input Component file to be run

Guide

Component uses Postfix Notation. Postfix Notion has the arguments first, and then the function or operation. In the below example, we are adding 1 and 2 with the + operator to get 3. Try typing the following into the interactive prompt:

1 2 +

It should look this this once it's been typed in and you press enter:

> 1 2 +
-> 3

Component has a lot of the operators you would expect from math and other languages:

+ addition
- subtraction
* mltiplication
/ division
^ exponentiation

Some that may be familar from other languages:

! logical not

And some that may not be as familar:

? conditional assignment

Component also has functions that can be called in the same was as operators:

sqrt square root

And build in constants:

e Euler's number
C Speed of light in m/s
pi Pi
true and false

Full List of Keywords

  • int converts types into NumericIntLiteral if possible
  • dec converts types into NumericDecLiteral if possible
  • bool converts types into BoolLiteral if possible
  • vars prints all variables
  • stack prints the current stack

Constants

  • e Euler's number
  • pi Pi
  • C Speed of light in m/s
  • true Boolean true
  • false Boolean false

Built-in Functions

  • sqrt Square root

Operations

  • + addition
  • - subtraction
  • * multiplication
  • / division
  • ^ exponentiation
  • ! logical not
  • ? conditional assignment

Basic Math Operations

Add two numbers together.

> 1 1 +
-> 2

This also works with - for subtraction, * for multiplication, and / for division.

Vector Operations (Coming Soon)

> 1 2 3 > 5 6 7 > x
-> 4 -8 4

Variables

Assign the value 2 to variable a.

> 2 a =
-> 2

Use the variable a.

a 4 *
-> 8

Conditional Assignment

This will conditionally assign 5 to b if a is true.

> true a =

> 5 b a ?

Variables are statically typed in Component. Here is an example usage of a variable.

image

Function

Create an addition function called foo. Note that to start a function you do in fact need to use the > again to tell the interpreter that the following is a function and should not be evaluated.

> > + foo func

> 1 2 foo
-> 3

Here is the example of caluclating the speed dilation of an object at velocity v in m/s for time t in seconds. More info about this in the section #Component-in-action

> > t 1 v 2 ^ C 2 ^ / - sqrt / s fn

Type Conversion

> 4 5 /
-> 0.8

> 4 5 / int
-> 0
> 2 dec
-> 1

Component in action

The following is a Component program to calculate the time dilation observed by an object moving at 300 m/s for 25 seconds.

image

After adding C as a constant and compressing this whole program into a single expression, here is the same code minus the variable assignment.

image

Here I created a function called s that computes the same equation.

image

A test file with the same functionality can be found here: space.

Convert to Assembly

Currently the interpreter creates x86-64 or RISC-V assembly as the code is being evaluated. In the future, an output file can be specified and the assembly will be put into that file and assembled.

image

Error Handling

Errors that occur in the interactive interpreter cause the line being interpreted to crash. When this happens, one of the following error messages will be displayed.

Assignment Type Mismatch [E1]

An Assignment Type Mismatch happens when you try to assign a value to an existing variable of a different type. In the following example, the variable a is created as a NumericIntLiteral type. Then the value 0.8 is attempted to be assigned the variable a but because 0.8 is of the type NumericDecLiteral, it fails with an Assignment Type Mismatch error. This means that variables are statically typed and cannot be changed during runtime.

> 1 a =
-> 1

> 4 5 / a =
Error: Assignment Type Mismatch [E1]
0.8 a =
    ^^^ cannot assign value 0.8 of type <NumericDecLiteral> to a variable of type <NumericIntLiteral>

Wrong Type [E2]

A Wrong Type error happens when you try to call an operation or a function on one or more variables of the wrong type. Here is an example of an identifier being used before it has been assigned. Since it does not get swapped out for a value, since it hasn't been assigned, it has the type Identifier and therefore is the wrong type. In the future, this will also happen for math operations on the type String.

> a 1 +
Error: Wrong Type [E2]
a 1 +
^ value is not a <NumericIntLiteral> or <NumericDecLiteral>

Invalid Type Cast [E3]

An Invalid Type Cast happens when you try to cast from type to type but there is not an operation where this is possible. Similar to the Wrong Type error, the example below shows how an Identifier that has not been assigned a value, is being attempted to cast to both a NumericDecLiteral with the keyword dec and a NumericIntLiteral with the keyword int. Since there has been no assignment to the variable a, it will not get swapped out for a value, and the type cannot be cast to either.

> a dec
Error: Invalid Type Cast [E3]
a dec
  ^^^ Cannot convert <Identifier> to <NumericDecLiteral>

> a int
Error: Invalid Type Cast [E3]
a int
  ^^^ Cannot convert <Identifier> to <NumericIntLiteral>

Stack Empty [E4]

The Stack Empty error happens when the function or operation that has been called requires more arguments than are currently on the stack. This is an indication that not enough variables where provided. In the example below, a single NumericIntLiteral has been added to the stack and then the Addition operation has been called. This gives and error because the Addition operation requires two arguments.

> 1 +
Error: Stack Empty [E4]

Operation Not Implemented [E5]

The Operation Not Implemented error occurs when a non-identifier symbol has been parsed that has not gotten functionality yet. Symbol here meaning one or many characters (e.g. foo or 123). Since symbols that are not keywords or existing identifiers get read as identifiers (so long they follow the identifier rules), there are few things that trigger the Operation Not Implemented error. The one class of symbols that do cause this error are characters like # and $ which have not been assigned any operation.

> #
Error: Operation Not Implemented [E5]

> $
Error: Operation Not Implemented [E5]

Example of errors

Here is an example of what this might look like in the interactive interpreter.

image

More About Component

Why is it called Component

Component is named after vectors, where a single scalar in a vector is called a "component" of that vector (e.g. < 1 2 3 > where 1, 2, and 3 are all components. This is also in reference to the name Basis, where a basis vector is a subset of a vector space where the vectors are linearly independent.

About

A programming language that compiles to x86-64 assembly for math using postfix notation

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages